<!DOCTYPE html><html><head><meta charset="utf-8"><title>Angular - 表单</title><base href="/"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="search" type="application/opensearchdescription+xml" href="assets/opensearch.xml"><link rel="icon" type="image/x-icon" href="assets/images/favicons/favicon.ico"><link rel="icon" type="image/png" href="assets/images/favicons/favicon-32x32.png" sizes="32x32"><link rel="icon" type="image/png" href="assets/images/favicons/favicon-194x194.png" sizes="194x194"><link rel="icon" type="image/png" href="assets/images/favicons/favicon-96x96.png" sizes="96x96"><link rel="icon" type="image/png" href="assets/images/favicons/favicon-16x16.png" sizes="16x16"><link rel="apple-touch-icon" sizes="144x144" href="assets/images/favicons/favicon-144x144.png"><link rel="apple-touch-icon-precomposed" sizes="144x144" href="assets/images/favicons/favicon-144x144.png"><link href="assets/fonts/Material_Icons.css" rel="stylesheet"><link href="assets/fonts/Droid_Sans_Mono.css" rel="stylesheet"><link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"><link rel="manifest" href="pwa-manifest.json"><meta name="theme-color" content="#1976d2"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="translucent"><script async="" src="assets/js/analytics.js"></script><script>!function(e,a,n,t,s,c,g){e.GoogleAnalyticsObject=s,e.ga=e.ga||function(){(e.ga.q=e.ga.q||[]).push(arguments)},e.ga.l=1*new Date,c=a.createElement(n),g=a.getElementsByTagName(n)[0],c.async=1,c.src="assets/js/analytics.js",~e.name.indexOf("NG_DEFER_BOOTSTRAP")||g.parentNode.insertBefore(c,g)}(window,document,"script",0,"ga")</script><script>window.onerror=function(){ga("send","exception",{exDescription:function(e,r,n,a,c){var l;e=e.replace(/^Error: /,""),l=c?c.stack.replace(/^Error: /,"").replace(e+"\n","").replace(/^ +/gm,"").replace(/^at /gm,"").replace(/(?: \(|@)http.+\/([^/)]+)\)?(?:\n|$)/gm,"@$1\n").replace(/ *\(eval code(:\d+:\d+)\)(?:\n|$)/gm,"@???$1\n"):r+":"+(n=n||"?")+":"+(a=a||"?");return(e+"\n"+l).substr(0,150)}.apply(null,arguments),exFatal:!0})}</script><script nomodule="" src="generated/ie-polyfills.min.js"></script><link rel="stylesheet" href="styles.10ba6936decaea45eabb.css"><style>@media screen and (-ms-high-contrast:active){.mat-toolbar{outline:solid 1px}}.mat-toolbar-row,.mat-toolbar-single-row{display:flex;box-sizing:border-box;padding:0 16px;width:100%;flex-direction:row;align-items:center;white-space:nowrap}.mat-toolbar-multiple-rows{display:flex;box-sizing:border-box;flex-direction:column;width:100%}.mat-toolbar-multiple-rows{min-height:64px}.mat-toolbar-row,.mat-toolbar-single-row{height:64px}@media (max-width:599px){.mat-toolbar-multiple-rows{min-height:56px}.mat-toolbar-row,.mat-toolbar-single-row{height:56px}}</style><style>.mat-icon{background-repeat:no-repeat;display:inline-block;fill:currentColor;height:24px;width:24px}.mat-icon.mat-icon-inline{font-size:inherit;height:inherit;line-height:inherit;width:inherit}[dir=rtl] .mat-icon-rtl-mirror{transform:scale(-1,1)}.mat-form-field:not(.mat-form-field-appearance-legacy) .mat-form-field-prefix .mat-icon,.mat-form-field:not(.mat-form-field-appearance-legacy) .mat-form-field-suffix .mat-icon{display:block}.mat-form-field:not(.mat-form-field-appearance-legacy) .mat-form-field-prefix .mat-icon-button .mat-icon,.mat-form-field:not(.mat-form-field-appearance-legacy) .mat-form-field-suffix .mat-icon-button .mat-icon{margin:auto}</style><style>.mat-button .mat-button-focus-overlay,.mat-icon-button .mat-button-focus-overlay{opacity:0}.mat-button:hover .mat-button-focus-overlay,.mat-stroked-button:hover .mat-button-focus-overlay{opacity:.04}@media (hover:none){.mat-button:hover .mat-button-focus-overlay,.mat-stroked-button:hover .mat-button-focus-overlay{opacity:0}}.mat-button,.mat-flat-button,.mat-icon-button,.mat-stroked-button{box-sizing:border-box;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:pointer;outline:0;border:none;-webkit-tap-highlight-color:transparent;display:inline-block;white-space:nowrap;text-decoration:none;vertical-align:baseline;text-align:center;margin:0;min-width:64px;line-height:36px;padding:0 16px;border-radius:4px;overflow:visible}.mat-button::-moz-focus-inner,.mat-flat-button::-moz-focus-inner,.mat-icon-button::-moz-focus-inner,.mat-stroked-button::-moz-focus-inner{border:0}.mat-button[disabled],.mat-flat-button[disabled],.mat-icon-button[disabled],.mat-stroked-button[disabled]{cursor:default}.mat-button.cdk-keyboard-focused .mat-button-focus-overlay,.mat-button.cdk-program-focused .mat-button-focus-overlay,.mat-flat-button.cdk-keyboard-focused .mat-button-focus-overlay,.mat-flat-button.cdk-program-focused .mat-button-focus-overlay,.mat-icon-button.cdk-keyboard-focused .mat-button-focus-overlay,.mat-icon-button.cdk-program-focused .mat-button-focus-overlay,.mat-stroked-button.cdk-keyboard-focused .mat-button-focus-overlay,.mat-stroked-button.cdk-program-focused .mat-button-focus-overlay{opacity:.12}.mat-button::-moz-focus-inner,.mat-flat-button::-moz-focus-inner,.mat-icon-button::-moz-focus-inner,.mat-stroked-button::-moz-focus-inner{border:0}.mat-raised-button{box-sizing:border-box;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:pointer;outline:0;border:none;-webkit-tap-highlight-color:transparent;display:inline-block;white-space:nowrap;text-decoration:none;vertical-align:baseline;text-align:center;margin:0;min-width:64px;line-height:36px;padding:0 16px;border-radius:4px;overflow:visible;transform:translate3d(0,0,0);transition:background .4s cubic-bezier(.25,.8,.25,1),box-shadow 280ms cubic-bezier(.4,0,.2,1)}.mat-raised-button::-moz-focus-inner{border:0}.mat-raised-button[disabled]{cursor:default}.mat-raised-button.cdk-keyboard-focused .mat-button-focus-overlay,.mat-raised-button.cdk-program-focused .mat-button-focus-overlay{opacity:.12}.mat-raised-button::-moz-focus-inner{border:0}._mat-animation-noopable.mat-raised-button{transition:none;animation:none}.mat-stroked-button{border:1px solid currentColor;padding:0 15px;line-height:34px}.mat-fab{box-sizing:border-box;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:pointer;outline:0;border:none;-webkit-tap-highlight-color:transparent;display:inline-block;white-space:nowrap;text-decoration:none;vertical-align:baseline;text-align:center;margin:0;min-width:64px;line-height:36px;padding:0 16px;border-radius:4px;overflow:visible;transform:translate3d(0,0,0);transition:background .4s cubic-bezier(.25,.8,.25,1),box-shadow 280ms cubic-bezier(.4,0,.2,1);min-width:0;border-radius:50%;width:56px;height:56px;padding:0;flex-shrink:0}.mat-fab::-moz-focus-inner{border:0}.mat-fab[disabled]{cursor:default}.mat-fab.cdk-keyboard-focused .mat-button-focus-overlay,.mat-fab.cdk-program-focused .mat-button-focus-overlay{opacity:.12}.mat-fab::-moz-focus-inner{border:0}._mat-animation-noopable.mat-fab{transition:none;animation:none}.mat-fab .mat-button-wrapper{padding:16px 0;display:inline-block;line-height:24px}.mat-mini-fab{box-sizing:border-box;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:pointer;outline:0;border:none;-webkit-tap-highlight-color:transparent;display:inline-block;white-space:nowrap;text-decoration:none;vertical-align:baseline;text-align:center;margin:0;min-width:64px;line-height:36px;padding:0 16px;border-radius:4px;overflow:visible;transform:translate3d(0,0,0);transition:background .4s cubic-bezier(.25,.8,.25,1),box-shadow 280ms cubic-bezier(.4,0,.2,1);min-width:0;border-radius:50%;width:40px;height:40px;padding:0;flex-shrink:0}.mat-mini-fab::-moz-focus-inner{border:0}.mat-mini-fab[disabled]{cursor:default}.mat-mini-fab.cdk-keyboard-focused .mat-button-focus-overlay,.mat-mini-fab.cdk-program-focused .mat-button-focus-overlay{opacity:.12}.mat-mini-fab::-moz-focus-inner{border:0}._mat-animation-noopable.mat-mini-fab{transition:none;animation:none}.mat-mini-fab .mat-button-wrapper{padding:8px 0;display:inline-block;line-height:24px}.mat-icon-button{padding:0;min-width:0;width:40px;height:40px;flex-shrink:0;line-height:40px;border-radius:50%}.mat-icon-button .mat-icon,.mat-icon-button i{line-height:24px}.mat-button-focus-overlay,.mat-button-ripple.mat-ripple{top:0;left:0;right:0;bottom:0;position:absolute;pointer-events:none;border-radius:inherit}.mat-button-focus-overlay{border-radius:inherit;opacity:0;transition:opacity .2s cubic-bezier(.35,0,.25,1),background-color .2s cubic-bezier(.35,0,.25,1)}._mat-animation-noopable .mat-button-focus-overlay{transition:none}@media screen and (-ms-high-contrast:active){.mat-button-focus-overlay{background-color:rgba(255,255,255,.5)}}.mat-button-ripple-round{border-radius:50%;z-index:1}.mat-button .mat-button-wrapper>*,.mat-fab .mat-button-wrapper>*,.mat-flat-button .mat-button-wrapper>*,.mat-icon-button .mat-button-wrapper>*,.mat-mini-fab .mat-button-wrapper>*,.mat-raised-button .mat-button-wrapper>*,.mat-stroked-button .mat-button-wrapper>*{vertical-align:middle}.mat-form-field:not(.mat-form-field-appearance-legacy) .mat-form-field-prefix .mat-icon-button,.mat-form-field:not(.mat-form-field-appearance-legacy) .mat-form-field-suffix .mat-icon-button{display:block;font-size:inherit;width:2.5em;height:2.5em}@media screen and (-ms-high-contrast:active){.mat-button,.mat-fab,.mat-flat-button,.mat-icon-button,.mat-mini-fab,.mat-raised-button{outline:solid 1px}}</style><style>.mat-drawer-container{position:relative;z-index:1;box-sizing:border-box;-webkit-overflow-scrolling:touch;display:block;overflow:hidden}.mat-drawer-container[fullscreen]{top:0;left:0;right:0;bottom:0;position:absolute}.mat-drawer-container[fullscreen].mat-drawer-opened{overflow:hidden}.mat-drawer-container.mat-drawer-container-explicit-backdrop .mat-drawer-side{z-index:3}.mat-drawer-container.ng-animate-disabled .mat-drawer-backdrop,.mat-drawer-container.ng-animate-disabled .mat-drawer-content,.ng-animate-disabled .mat-drawer-container .mat-drawer-backdrop,.ng-animate-disabled .mat-drawer-container .mat-drawer-content{transition:none}.mat-drawer-backdrop{top:0;left:0;right:0;bottom:0;position:absolute;display:block;z-index:3;visibility:hidden}.mat-drawer-backdrop.mat-drawer-shown{visibility:visible}.mat-drawer-transition .mat-drawer-backdrop{transition-duration:.4s;transition-timing-function:cubic-bezier(.25,.8,.25,1);transition-property:background-color,visibility}@media screen and (-ms-high-contrast:active){.mat-drawer-backdrop{opacity:.5}}.mat-drawer-content{position:relative;z-index:1;display:block;height:100%;overflow:auto}.mat-drawer-transition .mat-drawer-content{transition-duration:.4s;transition-timing-function:cubic-bezier(.25,.8,.25,1);transition-property:transform,margin-left,margin-right}.mat-drawer{position:relative;z-index:4;display:block;position:absolute;top:0;bottom:0;z-index:3;outline:0;box-sizing:border-box;overflow-y:auto;transform:translate3d(-100%,0,0)}@media screen and (-ms-high-contrast:active){.mat-drawer,[dir=rtl] .mat-drawer.mat-drawer-end{border-right:solid 1px currentColor}}@media screen and (-ms-high-contrast:active){.mat-drawer.mat-drawer-end,[dir=rtl] .mat-drawer{border-left:solid 1px currentColor;border-right:none}}.mat-drawer.mat-drawer-side{z-index:2}.mat-drawer.mat-drawer-end{right:0;transform:translate3d(100%,0,0)}[dir=rtl] .mat-drawer{transform:translate3d(100%,0,0)}[dir=rtl] .mat-drawer.mat-drawer-end{left:0;right:auto;transform:translate3d(-100%,0,0)}.mat-drawer-inner-container{width:100%;height:100%;overflow:auto;-webkit-overflow-scrolling:touch}.mat-sidenav-fixed{position:fixed}</style><style>.nav-link.highlight[_ngcontent-c5]{color:#ff0}</style><style>.mat-progress-bar{display:block;height:4px;overflow:hidden;position:relative;transition:opacity 250ms linear;width:100%}._mat-animation-noopable.mat-progress-bar{transition:none;animation:none}.mat-progress-bar .mat-progress-bar-element,.mat-progress-bar .mat-progress-bar-fill::after{height:100%;position:absolute;width:100%}.mat-progress-bar .mat-progress-bar-background{width:calc(100% + 10px)}@media screen and (-ms-high-contrast:active){.mat-progress-bar .mat-progress-bar-background{display:none}}.mat-progress-bar .mat-progress-bar-buffer{transform-origin:top left;transition:transform 250ms ease}@media screen and (-ms-high-contrast:active){.mat-progress-bar .mat-progress-bar-buffer{border-top:solid 5px;opacity:.5}}.mat-progress-bar .mat-progress-bar-secondary{display:none}.mat-progress-bar .mat-progress-bar-fill{animation:none;transform-origin:top left;transition:transform 250ms ease}@media screen and (-ms-high-contrast:active){.mat-progress-bar .mat-progress-bar-fill{border-top:solid 4px}}.mat-progress-bar .mat-progress-bar-fill::after{animation:none;content:'';display:inline-block;left:0}.mat-progress-bar[dir=rtl],[dir=rtl] .mat-progress-bar{transform:rotateY(180deg)}.mat-progress-bar[mode=query]{transform:rotateZ(180deg)}.mat-progress-bar[mode=query][dir=rtl],[dir=rtl] .mat-progress-bar[mode=query]{transform:rotateZ(180deg) rotateY(180deg)}.mat-progress-bar[mode=indeterminate] .mat-progress-bar-fill,.mat-progress-bar[mode=query] .mat-progress-bar-fill{transition:none}.mat-progress-bar[mode=indeterminate] .mat-progress-bar-primary,.mat-progress-bar[mode=query] .mat-progress-bar-primary{-webkit-backface-visibility:hidden;backface-visibility:hidden;animation:mat-progress-bar-primary-indeterminate-translate 2s infinite linear;left:-145.166611%}.mat-progress-bar[mode=indeterminate] .mat-progress-bar-primary.mat-progress-bar-fill::after,.mat-progress-bar[mode=query] .mat-progress-bar-primary.mat-progress-bar-fill::after{-webkit-backface-visibility:hidden;backface-visibility:hidden;animation:mat-progress-bar-primary-indeterminate-scale 2s infinite linear}.mat-progress-bar[mode=indeterminate] .mat-progress-bar-secondary,.mat-progress-bar[mode=query] .mat-progress-bar-secondary{-webkit-backface-visibility:hidden;backface-visibility:hidden;animation:mat-progress-bar-secondary-indeterminate-translate 2s infinite linear;left:-54.888891%;display:block}.mat-progress-bar[mode=indeterminate] .mat-progress-bar-secondary.mat-progress-bar-fill::after,.mat-progress-bar[mode=query] .mat-progress-bar-secondary.mat-progress-bar-fill::after{-webkit-backface-visibility:hidden;backface-visibility:hidden;animation:mat-progress-bar-secondary-indeterminate-scale 2s infinite linear}.mat-progress-bar[mode=buffer] .mat-progress-bar-background{-webkit-backface-visibility:hidden;backface-visibility:hidden;animation:mat-progress-bar-background-scroll 250ms infinite linear;display:block}.mat-progress-bar._mat-animation-noopable .mat-progress-bar-background,.mat-progress-bar._mat-animation-noopable .mat-progress-bar-buffer,.mat-progress-bar._mat-animation-noopable .mat-progress-bar-fill,.mat-progress-bar._mat-animation-noopable .mat-progress-bar-fill::after,.mat-progress-bar._mat-animation-noopable .mat-progress-bar-primary,.mat-progress-bar._mat-animation-noopable .mat-progress-bar-primary.mat-progress-bar-fill::after,.mat-progress-bar._mat-animation-noopable .mat-progress-bar-secondary,.mat-progress-bar._mat-animation-noopable .mat-progress-bar-secondary.mat-progress-bar-fill::after{animation:none;transition:none}@keyframes mat-progress-bar-primary-indeterminate-translate{0%{transform:translateX(0)}20%{animation-timing-function:cubic-bezier(.5,0,.70173,.49582);transform:translateX(0)}59.15%{animation-timing-function:cubic-bezier(.30244,.38135,.55,.95635);transform:translateX(83.67142%)}100%{transform:translateX(200.61106%)}}@keyframes mat-progress-bar-primary-indeterminate-scale{0%{transform:scaleX(.08)}36.65%{animation-timing-function:cubic-bezier(.33473,.12482,.78584,1);transform:scaleX(.08)}69.15%{animation-timing-function:cubic-bezier(.06,.11,.6,1);transform:scaleX(.66148)}100%{transform:scaleX(.08)}}@keyframes mat-progress-bar-secondary-indeterminate-translate{0%{animation-timing-function:cubic-bezier(.15,0,.51506,.40969);transform:translateX(0)}25%{animation-timing-function:cubic-bezier(.31033,.28406,.8,.73371);transform:translateX(37.65191%)}48.35%{animation-timing-function:cubic-bezier(.4,.62704,.6,.90203);transform:translateX(84.38617%)}100%{transform:translateX(160.27778%)}}@keyframes mat-progress-bar-secondary-indeterminate-scale{0%{animation-timing-function:cubic-bezier(.15,0,.51506,.40969);transform:scaleX(.08)}19.15%{animation-timing-function:cubic-bezier(.31033,.28406,.8,.73371);transform:scaleX(.4571)}44.15%{animation-timing-function:cubic-bezier(.4,.62704,.6,.90203);transform:scaleX(.72796)}100%{transform:scaleX(.08)}}@keyframes mat-progress-bar-background-scroll{to{transform:translateX(-8px)}}</style><script charset="utf-8" src="toc-toc-module-ngfactory.36694c537d7ff0b2c081.js"></script><script charset="utf-8" src="default~code-code-example-module-ngfactory~code-code-tabs-module-ngfactory~getting-started-ng-for-ng~82f414e5.c64b8abba8f3b7168616.js"></script><script charset="utf-8" src="default~code-code-example-module-ngfactory~code-code-tabs-module-ngfactory.98830c4eaea3268880de.js"></script><script charset="utf-8" src="code-code-example-module-ngfactory.bb14a03c7095ffd0e7bd.js"></script><script charset="utf-8" src="code-code-tabs-module-ngfactory.e688ffb25bac166802a3.js"></script><script charset="utf-8" src="live-example-live-example-module-ngfactory.fef451c7b16613f97732.js"></script><script charset="utf-8" src="21.d3ebf64aa7b6d3a4b8f6.js"></script><style>.mat-card{transition:box-shadow 280ms cubic-bezier(.4,0,.2,1);display:block;position:relative;padding:16px;border-radius:4px}.mat-card .mat-divider-horizontal{position:absolute;left:0;width:100%}[dir=rtl] .mat-card .mat-divider-horizontal{left:auto;right:0}.mat-card .mat-divider-horizontal.mat-divider-inset{position:static;margin:0}[dir=rtl] .mat-card .mat-divider-horizontal.mat-divider-inset{margin-right:0}@media screen and (-ms-high-contrast:active){.mat-card{outline:solid 1px}}.mat-card-actions,.mat-card-content,.mat-card-subtitle{display:block;margin-bottom:16px}.mat-card-title{display:block;margin-bottom:8px}.mat-card-actions{margin-left:-8px;margin-right:-8px;padding:8px 0}.mat-card-actions-align-end{display:flex;justify-content:flex-end}.mat-card-image{width:calc(100% + 32px);margin:0 -16px 16px -16px}.mat-card-footer{display:block;margin:0 -16px -16px -16px}.mat-card-actions .mat-button,.mat-card-actions .mat-raised-button{margin:0 8px}.mat-card-header{display:flex;flex-direction:row}.mat-card-header .mat-card-title{margin-bottom:12px}.mat-card-header-text{margin:0 16px}.mat-card-avatar{height:40px;width:40px;border-radius:50%;flex-shrink:0;object-fit:cover}.mat-card-title-group{display:flex;justify-content:space-between}.mat-card-sm-image{width:80px;height:80px}.mat-card-md-image{width:112px;height:112px}.mat-card-lg-image{width:152px;height:152px}.mat-card-xl-image{width:240px;height:240px;margin:-8px}.mat-card-title-group>.mat-card-xl-image{margin:-8px 0 8px 0}@media (max-width:599px){.mat-card-title-group{margin:0}.mat-card-xl-image{margin-left:0;margin-right:0}}.mat-card-content>:first-child,.mat-card>:first-child{margin-top:0}.mat-card-content>:last-child:not(.mat-card-footer),.mat-card>:last-child:not(.mat-card-footer){margin-bottom:0}.mat-card-image:first-child{margin-top:-16px;border-top-left-radius:inherit;border-top-right-radius:inherit}.mat-card>.mat-card-actions:last-child{margin-bottom:-8px;padding-bottom:0}.mat-card-actions .mat-button:first-child,.mat-card-actions .mat-raised-button:first-child{margin-left:0;margin-right:0}.mat-card-title{margin-bottom:8px}.mat-card-subtitle:not(:first-child),.mat-card-title:not(:first-child){margin-top:-4px}.mat-card-header .mat-card-subtitle:not(:first-child){margin-top:-8px}.mat-card>.mat-card-xl-image:first-child{margin-top:-8px}.mat-card>.mat-card-xl-image:last-child{margin-bottom:-8px}</style><style>.mat-tab-group{display:flex;flex-direction:column}.mat-tab-group.mat-tab-group-inverted-header{flex-direction:column-reverse}.mat-tab-label{height:48px;padding:0 24px;cursor:pointer;box-sizing:border-box;opacity:.6;min-width:160px;text-align:center;display:inline-flex;justify-content:center;align-items:center;white-space:nowrap;position:relative}.mat-tab-label:focus{outline:0}.mat-tab-label:focus:not(.mat-tab-disabled){opacity:1}@media screen and (-ms-high-contrast:active){.mat-tab-label:focus{outline:dotted 2px}}.mat-tab-label.mat-tab-disabled{cursor:default}@media screen and (-ms-high-contrast:active){.mat-tab-label.mat-tab-disabled{opacity:.5}}.mat-tab-label .mat-tab-label-content{display:inline-flex;justify-content:center;align-items:center;white-space:nowrap}@media screen and (-ms-high-contrast:active){.mat-tab-label{opacity:1}}@media (max-width:599px){.mat-tab-label{padding:0 12px}}@media (max-width:959px){.mat-tab-label{padding:0 12px}}.mat-tab-group[mat-stretch-tabs]>.mat-tab-header .mat-tab-label{flex-basis:0;flex-grow:1}.mat-tab-body-wrapper{position:relative;overflow:hidden;display:flex;transition:height .5s cubic-bezier(.35,0,.25,1)}.mat-tab-body{top:0;left:0;right:0;bottom:0;position:absolute;display:block;overflow:hidden;flex-basis:100%}.mat-tab-body.mat-tab-body-active{position:relative;overflow-x:hidden;overflow-y:auto;z-index:1;flex-grow:1}.mat-tab-group.mat-tab-group-dynamic-height .mat-tab-body.mat-tab-body-active{overflow-y:hidden}</style><style>.mat-tab-header{display:flex;overflow:hidden;position:relative;flex-shrink:0}.mat-tab-label{height:48px;padding:0 24px;cursor:pointer;box-sizing:border-box;opacity:.6;min-width:160px;text-align:center;display:inline-flex;justify-content:center;align-items:center;white-space:nowrap;position:relative}.mat-tab-label:focus{outline:0}.mat-tab-label:focus:not(.mat-tab-disabled){opacity:1}@media screen and (-ms-high-contrast:active){.mat-tab-label:focus{outline:dotted 2px}}.mat-tab-label.mat-tab-disabled{cursor:default}@media screen and (-ms-high-contrast:active){.mat-tab-label.mat-tab-disabled{opacity:.5}}.mat-tab-label .mat-tab-label-content{display:inline-flex;justify-content:center;align-items:center;white-space:nowrap}@media screen and (-ms-high-contrast:active){.mat-tab-label{opacity:1}}@media (max-width:599px){.mat-tab-label{min-width:72px}}.mat-ink-bar{position:absolute;bottom:0;height:2px;transition:.5s cubic-bezier(.35,0,.25,1)}.mat-tab-group-inverted-header .mat-ink-bar{bottom:auto;top:0}@media screen and (-ms-high-contrast:active){.mat-ink-bar{outline:solid 2px;height:0}}.mat-tab-header-pagination{position:relative;display:none;justify-content:center;align-items:center;min-width:32px;cursor:pointer;z-index:2}.mat-tab-header-pagination-controls-enabled .mat-tab-header-pagination{display:flex}.mat-tab-header-pagination-before,.mat-tab-header-rtl .mat-tab-header-pagination-after{padding-left:4px}.mat-tab-header-pagination-before .mat-tab-header-pagination-chevron,.mat-tab-header-rtl .mat-tab-header-pagination-after .mat-tab-header-pagination-chevron{transform:rotate(-135deg)}.mat-tab-header-pagination-after,.mat-tab-header-rtl .mat-tab-header-pagination-before{padding-right:4px}.mat-tab-header-pagination-after .mat-tab-header-pagination-chevron,.mat-tab-header-rtl .mat-tab-header-pagination-before .mat-tab-header-pagination-chevron{transform:rotate(45deg)}.mat-tab-header-pagination-chevron{border-style:solid;border-width:2px 2px 0 0;content:'';height:8px;width:8px}.mat-tab-header-pagination-disabled{box-shadow:none;cursor:default}.mat-tab-label-container{display:flex;flex-grow:1;overflow:hidden;z-index:1}.mat-tab-list{flex-grow:1;position:relative;transition:transform .5s cubic-bezier(.35,0,.25,1)}.mat-tab-labels{display:flex}[mat-align-tabs=center] .mat-tab-labels{justify-content:center}[mat-align-tabs=end] .mat-tab-labels{justify-content:flex-end}</style><style>.mat-tab-body-content{height:100%;overflow:auto}.mat-tab-group-dynamic-height .mat-tab-body-content{overflow:hidden}</style></head><body><aio-shell ng-version="7.0.0" class="mode-stable sidenav-open page-guide-forms folder-guide view-SideNav aio-notification-show"><div id="top-of-page"></div><mat-toolbar class="app-toolbar no-print mat-toolbar mat-primary mat-toolbar-multiple-rows" color="primary"><mat-toolbar-row class="notification-container mat-toolbar-row"><aio-notification expirationdate="2019-03-01" notificationid="survey-february-2019" class="ng-tns-c2-0 ng-trigger ng-trigger-hideAnimation"><span class="content"><a href="http://bit.ly/angular-survey-2019" target="_blank"><mat-icon aria-label="Announcement" class="icon mat-icon" role="img" svgicon="insert_comment" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20 2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h14l4 4V4c0-1.1-.9-2-2-2zm-2 12H6v-2h12v2zm0-3H6V9h12v2zm0-3H6V6h12v2z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg></mat-icon><span class="message"><b>填写这份《一分钟调查》</b>，帮我们（开发组）做得更好！</span><span class="action-button">去填写</span></a></span><button class="close-button mat-icon-button" aria-label="Close" mat-icon-button=""><span class="mat-button-wrapper"><mat-icon aria-label="Dismiss notification" class="mat-icon ng-tns-c2-0" role="img" svgicon="close" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg></mat-icon></span><div class="mat-button-ripple mat-ripple mat-button-ripple-round" matripple=""></div><div class="mat-button-focus-overlay"></div></button></aio-notification></mat-toolbar-row><mat-toolbar-row class="mat-toolbar-row"><button class="hamburger mat-button" mat-button="" title="Docs menu"><span class="mat-button-wrapper"><mat-icon class="mat-icon" role="img" svgicon="menu" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"></path></svg></mat-icon></span><div class="mat-button-ripple mat-ripple" matripple=""></div><div class="mat-button-focus-overlay"></div></button><a class="nav-link home" href="/"><img alt="Home" height="40" src="assets/images/logos/angular/logo-nav@2x.png" title="Home" width="150" class="ng-star-inserted"></a><aio-top-menu _nghost-c5="" class="ng-star-inserted"><ul _ngcontent-c5="" role="navigation"><li _ngcontent-c5="" class="ng-star-inserted"><a _ngcontent-c5="" class="nav-link" href="features" title="特性"><span _ngcontent-c5="" class="nav-link-inner">特性</span></a></li><li _ngcontent-c5="" class="ng-star-inserted"><a _ngcontent-c5="" class="nav-link" href="docs" title="文档"><span _ngcontent-c5="" class="nav-link-inner">文档</span></a></li><li _ngcontent-c5="" class="ng-star-inserted"><a _ngcontent-c5="" class="nav-link" href="resources" title="资源"><span _ngcontent-c5="" class="nav-link-inner">资源</span></a></li><li _ngcontent-c5="" class="ng-star-inserted"><a _ngcontent-c5="" class="nav-link" href="events" title="会议"><span _ngcontent-c5="" class="nav-link-inner">会议</span></a></li><li _ngcontent-c5="" class="ng-star-inserted"><a _ngcontent-c5="" class="nav-link" href="https://blog.angular.io/" title="博客"><span _ngcontent-c5="" class="nav-link-inner">博客</span></a></li><li _ngcontent-c5="" class="ng-star-inserted"><a _ngcontent-c5="" class="nav-link" href="translations/cn/home" title="关于中文版"><span _ngcontent-c5="" class="nav-link-inner">关于中文版</span></a></li></ul></aio-top-menu><aio-search-box class="search-container"><input aria-label="search" placeholder="搜索" type="search"></aio-search-box><div class="toolbar-external-icons-container"><a aria-label="Angular on twitter" href="https://twitter.com/angular" title="Twitter"><mat-icon class="mat-icon" role="img" svgicon="logos:twitter" aria-hidden="true"><svg focusable="false" viewBox="0 0 50 59" xmlns="http://www.w3.org/2000/svg"><path d="M50,9.3c-1.8,0.8-3.8,1.4-5.9,1.6c2.1-1.3,3.7-3.3,4.5-5.7c-2,1.2-4.2,2-6.5,2.5c-1.9-2-4.5-3.2-7.5-3.2c-5.7,0-10.3,4.6-10.3,10.3c0,0.8,0.1,1.6,0.3,2.3C16.1,16.7,8.5,12.6,3.5,6.4c-0.9,1.5-1.4,3.3-1.4,5.2c0,3.6,1.8,6.7,4.6,8.5C5,20,3.4,19.6,2,18.8c0,0,0,0.1,0,0.1c0,5,3.5,9.1,8.2,10.1c-0.9,0.2-1.8,0.4-2.7,0.4c-0.7,0-1.3-0.1-1.9-0.2c1.3,4.1,5.1,7,9.6,7.1c-3.5,2.8-7.9,4.4-12.7,4.4c-0.8,0-1.6,0-2.4-0.1c4.5,2.9,9.9,4.6,15.7,4.6c18.9,0,29.2-15.6,29.2-29.2c0-0.4,0-0.9,0-1.3C46.9,13.2,48.6,11.4,50,9.3z"></path></svg></mat-icon></a><a aria-label="Angular on github" href="https://github.com/angular/angular" title="GitHub"><mat-icon class="mat-icon" role="img" svgicon="logos:github" aria-hidden="true"><svg focusable="false" viewBox="0 0 51.8 50.4" xmlns="http://www.w3.org/2000/svg"><path d="M25.9,0.2C11.8,0.2,0.3,11.7,0.3,25.8c0,11.3,7.3,20.9,17.5,24.3c1.3,0.2,1.7-0.6,1.7-1.2c0-0.6,0-2.6,0-4.8c-7.1,1.5-8.6-3-8.6-3c-1.2-3-2.8-3.7-2.8-3.7c-2.3-1.6,0.2-1.6,0.2-1.6c2.6,0.2,3.9,2.6,3.9,2.6c2.3,3.9,6,2.8,7.5,2.1c0.2-1.7,0.9-2.8,1.6-3.4c-5.7-0.6-11.7-2.8-11.7-12.7c0-2.8,1-5.1,2.6-6.9c-0.3-0.7-1.1-3.3,0.3-6.8c0,0,2.1-0.7,7,2.6c2-0.6,4.2-0.9,6.4-0.9c2.2,0,4.4,0.3,6.4,0.9c4.9-3.3,7-2.6,7-2.6c1.4,3.5,0.5,6.1,0.3,6.8c1.6,1.8,2.6,4.1,2.6,6.9c0,9.8-6,12-11.7,12.6c0.9,0.8,1.7,2.4,1.7,4.7c0,3.4,0,6.2,0,7c0,0.7,0.5,1.5,1.8,1.2c10.2-3.4,17.5-13,17.5-24.3C51.5,11.7,40.1,0.2,25.9,0.2z"></path></svg></mat-icon></a></div></mat-toolbar-row></mat-toolbar><mat-sidenav-container class="sidenav-container mat-drawer-container mat-sidenav-container mat-drawer-transition has-floating-toc" role="main"><div class="mat-drawer-backdrop ng-star-inserted"></div><div class="cdk-visually-hidden cdk-focus-trap-anchor"></div><mat-sidenav class="sidenav mat-drawer mat-sidenav ng-tns-c7-1 ng-trigger ng-trigger-transform mat-drawer-side ng-star-inserted" tabindex="-1" style="transform:none;visibility:visible"><div class="mat-drawer-inner-container"><aio-nav-menu><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-1 collapsed ng-star-inserted" style="position:relative" href="guide/quickstart" title="对 Angular 和 Angular CLI 基础知识的简短介绍" target="_self">快速上手</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button class="vertical-menu-item heading level-1 collapsed ng-star-inserted" type="button" title="此《英雄指南》教程会带你用 TypeScript 一步步创建一个 Angular 应用。" aria-pressed="false">教程<mat-icon class="rotating-icon mat-icon" role="img" svgicon="keyboard_arrow_right" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-1 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="tutorial" title="《英雄指南》教程简介" target="_self">简介</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="tutorial/toh-pt0" title="创建应用的外壳" target="_self">应用的“外壳”</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="tutorial/toh-pt1" title="第一部分：构建一个简单的英雄编辑器" target="_self">1. 英雄编辑器</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="tutorial/toh-pt2" title="第二部分：构建一个主从结构的页面，用于展现英雄列表。" target="_self">2. 显示英雄列表</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="tutorial/toh-pt3" title="第三部分：把主从结构的页面重构成多个组件。" target="_self">3. 主从组件</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="tutorial/toh-pt4" title="第四部分：创建一个可复用的服务来管理英雄数据。" target="_self">4. 服务</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="tutorial/toh-pt5" title="第五部分：添加 Angular 路由器，并且学习在视图之间导航。" target="_self">5. 路由</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="tutorial/toh-pt6" title="第六部分：通过 HTTP 来获取并保存英雄数据。" target="_self">6. HTTP</a></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button class="vertical-menu-item heading level-1 expanded selected ng-star-inserted" type="button" title="学习 Angular 的核心知识" aria-pressed="true">核心知识<mat-icon class="rotating-icon mat-icon" role="img" svgicon="keyboard_arrow_right" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-1 expanded selected"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button class="vertical-menu-item heading level-2 collapsed ng-star-inserted" type="button" title="Angular 应用的基本构造块。" aria-pressed="false">架构<mat-icon class="rotating-icon mat-icon" role="img" svgicon="keyboard_arrow_right" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-2 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/architecture" title="Angular 应用的基本构造块" target="_self">架构概览</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/architecture-modules" title="关于模块。" target="_self">模块（NgModule）简介</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/architecture-components" title="关于组件、模板和视图。" target="_self">组件简介</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/architecture-services" title="关于服务与依赖注入。" target="_self">服务与 DI 简介</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/architecture-next-steps" title="学完基础知识之后……" target="_self">后续步骤</a></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button class="vertical-menu-item heading level-2 collapsed ng-star-inserted" type="button" title="使用数据绑定构建动态视图" aria-pressed="false">组件与模板<mat-icon class="rotating-icon mat-icon" role="img" svgicon="keyboard_arrow_right" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-2 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/displaying-data" title="属性绑定可以帮助应用把数据显示在界面上" target="_self">显示数据</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/template-syntax" title="学习如何写模板，以便借助数据绑定机制显示数据并响应事件。" target="_self">模板语法</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/user-input" title="用户输入会触发 DOM 事件。Angular 会通过事件绑定来监听那些事件，并把修改后的值传回应用的组件和模型中。" target="_self">用户输入</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/lifecycle-hooks" title="Angular 调用指令和组件的生命周期钩子函数，包括它的创建、变更和销毁时。" target="_self">生命周期钩子</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/component-interaction" title="在不同的指令和组件之间共享信息" target="_self">组件交互</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/component-styles" title="添加专属于某个组件的样式" target="_self">组件样式</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/elements" title="把组件转换成自定义元素。" target="_self">Angular 自定义元素</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/dynamic-component-loader" title="动态加载组件" target="_self">动态组件</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/attribute-directives" title="属性型指令把行为添加到现有元素上。" target="_self">属性型指令</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/structural-directives" title="结构型指令可以操纵页面的布局" target="_self">结构型指令</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/pipes" title="管道可以在模板中转换显示的内容。" target="_self">管道</a></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button class="vertical-menu-item heading level-2 expanded selected ng-star-inserted" type="button" title="Angular 的表单" aria-pressed="true">表单<mat-icon class="rotating-icon mat-icon" role="img" svgicon="keyboard_arrow_right" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-2 expanded selected"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/forms-overview" title="表单可以创建集中、高效、引人注目的输入体验。Angular 表单可以协调一组数据绑定控件，跟踪变更，验证输入，并表达错误信息。" target="_self">简介</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/reactive-forms" title="使用 FormBuilder、表单组和表单数组创建响应式表单。" target="_self">响应式表单</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 expanded selected ng-star-inserted" style="position:relative" href="guide/forms" title="使用指令和 Angular 模板语法创建模板驱动表单。" target="_self">模板驱动表单</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/form-validation" title="验证用户的表单输入" target="_self">表单验证</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/dynamic-form" title="使用 FormGroup 渲染动态表单。" target="_self">动态表单</a></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button class="vertical-menu-item heading level-2 collapsed ng-star-inserted" type="button" title="Observable 与 RxJS" aria-pressed="false">Observable 与 RxJS<mat-icon class="rotating-icon mat-icon" role="img" svgicon="keyboard_arrow_right" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-2 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/observables" title="" target="_self">可观察对象(Observable)</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/rx-library" title="" target="_self">RxJS 库</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/observables-in-angular" title="" target="_self">Angular 中的可观察对象</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/practical-observable-usage" title="" target="_self">用法实战</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/comparing-observables" title="" target="_self">与其它技术的比较</a></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/bootstrapping" title="在应用的根模块（AppModule）中告诉 Angular 如何构造并引导引用。" target="_self">引导启动</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button class="vertical-menu-item heading level-2 collapsed ng-star-inserted" type="button" title="Angular 中的模块" aria-pressed="false">NgModule<mat-icon class="rotating-icon mat-icon" role="img" svgicon="keyboard_arrow_right" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-2 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/ngmodules" title="使用 NgModule 让你的应用更高效" target="_self">NgModule 简介</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/ngmodule-vs-jsmodule" title="JavaScript 模块和 NgModule 之间的差异" target="_self">JS 模块 vs NgModule</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/frequent-ngmodules" title="介绍最常用的 NgModule" target="_self">常用模块</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/module-types" title="介绍特性模块的几种类型" target="_self">特性模块的分类</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/entry-components" title="关于 Angular 中入口组件的一切" target="_self">入口组件</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/feature-modules" title="创建特性模块，以组织你的代码" target="_self">特性模块</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/providers" title="服务提供商与 NgModule" target="_self">服务提供商</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/singleton-services" title="创建单例服务" target="_self">单例服务</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/lazy-loading-ngmodules" title="惰性加载模块，以提高应用的性能" target="_self">惰性加载的特性模块</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/sharing-ngmodules" title="共享 NgModule 让你的应用现代化。" target="_self">共享 NgModule</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/ngmodule-api" title="理解 NgModule 的那些细节。" target="_self">NgModule API</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/ngmodule-faq" title="回答关于 NgModules 的常见问题。" target="_self">NgModule 常见问题</a></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button class="vertical-menu-item heading level-2 collapsed ng-star-inserted" type="button" title="依赖注入：创建并注入各种服务。" aria-pressed="false">依赖注入<mat-icon class="rotating-icon mat-icon" role="img" svgicon="keyboard_arrow_right" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-2 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/dependency-injection" title="Angular 的依赖注入系统能够为 Angular 创建的类创建并交付它们所依赖的服务。" target="_self">Angular 依赖注入</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/hierarchical-dependency-injection" title="与组件树平行的注入器树，并支持嵌套的依赖。" target="_self">多级注入器</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/dependency-injection-providers" title="各种提供商类型的更多知识。" target="_self">DI 提供商</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/dependency-injection-in-action" title="依赖注入的使用技巧" target="_self">DI 实战</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/dependency-injection-navtree" title="使用注入器树来查找父组件。" target="_self">浏览组件树</a></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/http" title="通过 HTTP 协议与远程服务器对话。" target="_self">HttpClient</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/router" title="揭示如何通过 Angular 路由进行基本的屏幕导航。" target="_self">路由与导航</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button class="vertical-menu-item heading level-2 collapsed ng-star-inserted" type="button" title="Angular 动画系统指南" aria-pressed="false">动画<mat-icon class="rotating-icon mat-icon" role="img" svgicon="keyboard_arrow_right" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-2 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/animations" title="Angular 动画的基础技术。" target="_self">简介</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/transition-and-triggers" title="转场与触发器的高级技术。" target="_self">转场与触发器</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/complex-animation-sequences" title="复杂的 Angular 动画序列。" target="_self">复杂序列</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/reusable-animations" title="创建可复用的动画。" target="_self">可复用动画</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/route-animations" title="为路由提供转场动画。" target="_self">路由转场动画</a></div></aio-nav-item></div></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button class="vertical-menu-item heading level-1 collapsed ng-star-inserted" type="button" title="把 Angular 用到你的实际工作中的一些技巧" aria-pressed="false">其它技术<mat-icon class="rotating-icon mat-icon" role="img" svgicon="keyboard_arrow_right" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-1 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/security" title="Angular 应用开发中的安全技术。" target="_self">安全</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/i18n" title="把应用模板中的文本翻译成多种语言。" target="_self">国际化 (i18n)</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button class="vertical-menu-item heading level-2 collapsed ng-star-inserted" type="button" title="Angular Service Worker: 控制应用资源的缓存。" aria-pressed="false">Service Worker 与 PWA<mat-icon class="rotating-icon mat-icon" role="img" svgicon="keyboard_arrow_right" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-2 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/service-worker-intro" title="Angular 对 Service Worker 的实现提升了慢速或不稳定的网络连接下的用户体验。" target="_self">简介</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/service-worker-getting-started" title="在 CLI 项目中启用 Service Worker，并在浏览器中查看效果。" target="_self">快速起步</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/service-worker-communications" title="那些能让你和 Angular 的 Service Worker 通讯的服务类。" target="_self">与 Service Worker 通讯</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/service-worker-devops" title="使用 Service Worker 运行应用、管理应用更新、调试以及杀掉正在运行的应用。" target="_self">生产环境下的 Service Worker</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/service-worker-config" title="配置 Service Worker 的缓存行为。" target="_self">Service Worker 配置</a></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/universal" title="使用 Angular Universal 在服务端渲染 HTML。" target="_self">服务端渲染</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button class="vertical-menu-item heading level-2 collapsed ng-star-inserted" type="button" title="把 AngularJS 应用增量式的升级到 Angular。" aria-pressed="false">从 AngularJS 升级<mat-icon class="rotating-icon mat-icon" role="img" svgicon="keyboard_arrow_right" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-2 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/upgrade" title="把 AngularJS 应用增量式的升级到 Angular。" target="_self">升级步骤</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/upgrade-performance" title="用更灵活的方式把 AngularJS 升级到 Angular" target="_self">更关注性能的升级方式</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/ajs-quick-reference" title="学习如何把 AngularJS 的概念映射到 Angular 中。" target="_self">AngularJS 与 Angular 的概念对照</a></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button class="vertical-menu-item heading level-2 collapsed ng-star-inserted" type="button" title="使用共享库扩展 Angular" aria-pressed="false">Angular 库开发<mat-icon class="rotating-icon mat-icon" role="img" svgicon="keyboard_arrow_right" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-2 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/libraries" title="理解何时以及如何使用和创建库。" target="_self">库概览</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/using-libraries" title="把已发布的库集成进你的应用中。" target="_self">使用已发布的库</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/creating-libraries" title="通过创建、发布和使用你自己的库来扩展 Angular" target="_self">创建库</a></div></aio-nav-item></div></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button class="vertical-menu-item heading level-1 collapsed ng-star-inserted" type="button" title="关于环境搭建、构建、测试、部署环境与工具的信息。" aria-pressed="false">环境搭建与部署<mat-icon class="rotating-icon mat-icon" role="img" svgicon="keyboard_arrow_right" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-1 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/file-structure" title="Angular 工作区在文件系统中是怎样的。" target="_self">项目文件结构</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/workspace-config" title="&quot;angular.json&quot; 包含供 CLI 命令使用的工作区和项目默认配置。" target="_self">工作区配置</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/npm-packages" title="开发期间和运行期间所需的 npm 包的说明。" target="_self">npm 包</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/typescript-configuration" title="给 Angular 开发者的 TypeScript 配置。" target="_self">TypeScript 配置</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/aot-compiler" title="了解为何以及如何使用预先（AOT）编译器。" target="_self">预先（AOT）编译</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/build" title="构建应用及为应用启动开发服务器。" target="_self">构建与运行</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/testing" title="测试 Angular 应用的技巧与实践。" target="_self">测试</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/deployment" title="了解如何部署 Angular 应用。" target="_self">发布</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/browser-support" title="浏览器支持与腻子脚本指南。" target="_self">浏览器支持</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button class="vertical-menu-item heading level-2 collapsed ng-star-inserted" type="button" title="整合开发环境和工具。" aria-pressed="false">开发工具集成<mat-icon class="rotating-icon mat-icon" role="img" svgicon="keyboard_arrow_right" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-2 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-3 collapsed ng-star-inserted" style="position:relative" href="guide/language-service" title="使用 Angular 语言服务加速开发。" target="_self">语言服务</a></div></aio-nav-item></div></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button class="vertical-menu-item heading level-1 collapsed ng-star-inserted" type="button" title="Angular 的版本发布实践、更新与升级。" aria-pressed="false">发布信息<mat-icon class="rotating-icon mat-icon" role="img" svgicon="keyboard_arrow_right" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-1 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/updating" title="如何把 Angular 应用和库升级到最新版本。" target="_self">保持最新</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/releases" title="Angular 的版本、发布、支持、弃用策略与实践。" target="_self">Angular 发布策略与实践</a></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button class="vertical-menu-item heading level-1 collapsed ng-star-inserted" type="button" title="Angular 语法、编码、术语汇总。" aria-pressed="false">快捷手册<mat-icon class="rotating-icon mat-icon" role="img" svgicon="keyboard_arrow_right" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-1 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/cheatsheet" title="关于 Angular 常用编码技术的快速指南。" target="_self">速查表</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/styleguide" title="写出 Angular 风格的程序" target="_self">风格指南</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="guide/glossary" title="Angular 中最重要的词汇的简要定义。" target="_self">词汇表</a></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><button class="vertical-menu-item heading level-1 collapsed ng-star-inserted" type="button" title="Angular CLI 命令参考手册。" aria-pressed="false">CLI 命令<mat-icon class="rotating-icon mat-icon" role="img" svgicon="keyboard_arrow_right" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><div class="heading-children level-1 collapsed"><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli" title="CLI 工具介绍、命令、语法" target="_self">概览</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli/add" title="ng add." target="_self">ng add</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli/build" title="ng build." target="_self">ng build</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli/config" title="ng config." target="_self">ng config</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli/doc" title="ng doc." target="_self">ng doc</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli/e2e" title="ng e2e." target="_self">ng e2e</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli/generate" title="ng generate." target="_self">ng generate</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli/help" title="ng help." target="_self">ng help</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli/lint" title="ng lint." target="_self">ng lint</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli/new" title="ng new." target="_self">ng new</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli/run" title="ng run." target="_self">ng run</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli/serve" title="ng serve." target="_self">ng serve</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli/test" title="ng test." target="_self">ng test</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli/update" title="ng update." target="_self">ng update</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli/version" title="ng version." target="_self">ng version</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-2 collapsed ng-star-inserted" style="position:relative" href="cli/xi18n" title="ng xi18n." target="_self">ng xi18n</a></div></aio-nav-item></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-1 collapsed ng-star-inserted" style="position:relative" href="api" title="关于 Angular 中类和值的详细信息。" target="_self">API 参考手册</a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><div class="mat-divider ng-star-inserted" style="margin:4px 20px;border-top:1px solid #d3d3d3"></div></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-1 collapsed ng-star-inserted" style="position:relative" href="https://ng-china.org" title="2018 ngChina 开发者大会" target="_blank">2018 ngChina @ 杭州<mat-icon class="mat-icon material-icons ng-star-inserted" role="img" aria-hidden="true">open_in_new</mat-icon></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-1 collapsed ng-star-inserted" style="position:relative" href="https://github.com/ng-docs/ng-docs.github.io/issues" title="github 上的中文互助问答区" target="_blank">互助问答<mat-icon class="mat-icon material-icons ng-star-inserted" role="img" aria-hidden="true">open_in_new</mat-icon></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-1 collapsed ng-star-inserted" style="position:relative" href="https://material.angular.cn" title="Angular Material 组件库的中文文档" target="_blank">官方 Material 组件库<mat-icon class="mat-icon material-icons ng-star-inserted" role="img" aria-hidden="true">open_in_new</mat-icon></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-1 collapsed ng-star-inserted" style="position:relative" href="https://ng.ant.design/" title="Ant Design 的 Angular 实现，服务于企业级后台产品。" target="_blank">ng-zorro 组件库<mat-icon class="mat-icon material-icons ng-star-inserted" role="img" aria-hidden="true">open_in_new</mat-icon></a></div></aio-nav-item><aio-nav-item class="ng-star-inserted"><div class="ng-star-inserted"><a class="vertical-menu-item level-1 collapsed ng-star-inserted" style="position:relative" href="https://ng.mobile.ant.design/" title="Ant Design Mobile 的 Angular 实现，服务于无线产品。" target="_blank">ng-zorro mobile 组件库<mat-icon class="mat-icon material-icons ng-star-inserted" role="img" aria-hidden="true">open_in_new</mat-icon></a></div></aio-nav-item></aio-nav-menu><div class="doc-version"><aio-select><div class="form-select-menu"><button class="form-select-button"><strong></strong>stable (v8.0.0-beta.4)</button></div></aio-select></div></div></mat-sidenav><div class="cdk-visually-hidden cdk-focus-trap-anchor"></div><mat-sidenav-content cdkscrollable="" class="mat-drawer-content mat-sidenav-content ng-star-inserted" style="margin-left:260px"><main class="sidenav-content" role="main" id="guide-forms"><aio-mode-banner></aio-mode-banner><aio-doc-viewer class=""><div style="opacity:1"><div class="github-links"><a href="https://github.com/angular/angular-cn/edit/aio/aio/content/guide/forms.md?message=docs%3A%20请简述你的修改..." aria-label="提供编辑建议" title="提供编辑建议"><i class="material-icons" aria-hidden="true" role="img">mode_edit</i></a></div><div class="content"><h1 id="template-driven-forms" translation-result="on">表单<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#template-driven-forms"><i class="material-icons">link</i></a></h1><aio-toc class="embedded" ng-version="7.0.0"><div class="toc-inner no-print collapsed ng-star-inserted"><button aria-label="Expand/collapse contents" class="toc-heading embedded secondary ng-star-inserted" title="Expand/collapse contents" type="button" aria-pressed="false">目录<mat-icon class="rotating-icon mat-icon collapsed" role="img" svgicon="keyboard_arrow_right" aria-hidden="true"><svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"></path></svg></mat-icon></button><ul class="toc-list embedded"><li title="模板驱动表单简介link" class="h2 ng-star-inserted"><a href="guide/forms#introduction-to-template-driven-forms">模板驱动表单简介</a></li><li title="模板驱动表单link" class="h2 ng-star-inserted"><a href="guide/forms#template-driven-forms-1">模板驱动表单</a></li><li title="准备工作link" class="h2 ng-star-inserted"><a href="guide/forms#setup">准备工作</a></li><li title="创建 Hero 模型类link" class="h2 secondary ng-star-inserted"><a href="guide/forms#create-the-hero-model-class">创建 Hero 模型类</a></li><li title="创建表单组件link" class="h2 secondary ng-star-inserted"><a href="guide/forms#create-a-form-component">创建表单组件</a></li><li title="修改 app.module.tslink" class="h2 secondary ng-star-inserted"><a href="guide/forms#revise-appmodulets">修改 <em>app.module.ts</em></a></li><li title="修改 app.component.tslink" class="h2 secondary ng-star-inserted"><a href="guide/forms#revise-appcomponenthtml">修改 <em>app.component.ts</em></a></li><li title="创建初始 HTML 表单模板link" class="h2 secondary ng-star-inserted"><a href="guide/forms#create-an-initial-html-form-template">创建初始 HTML 表单模板</a></li><li title="用 ngFor 添加超能力link" class="h2 secondary ng-star-inserted"><a href="guide/forms#add-powers-with-ngfor">用 <strong><em>ngFor</em></strong> 添加超能力</a></li><li title="使用 ngModel 进行双向数据绑定link" class="h2 secondary ng-star-inserted"><a href="guide/forms#two-way-data-binding-with-ngmodel">使用 <em>ngModel</em> 进行双向数据绑定</a></li><li title="NgForm 指令link" class="h3 secondary ng-star-inserted"><a href="guide/forms#the-ngform-directive"><em>NgForm</em> 指令</a></li><li title="通过 ngModel 跟踪修改状态与有效性验证link" class="h2 secondary ng-star-inserted"><a href="guide/forms#track-control-state-and-validity-with-ngmodel">通过 <strong>ngModel</strong> 跟踪修改状态与有效性验证</a></li><li title="添加用于视觉反馈的自定义 CSSlink" class="h2 secondary ng-star-inserted"><a href="guide/forms#add-custom-css-for-visual-feedback">添加用于视觉反馈的自定义 CSS</a></li><li title="显示和隐藏验证错误信息link" class="h2 secondary ng-star-inserted"><a href="guide/forms#show-and-hide-validation-error-messages">显示和隐藏验证错误信息</a></li><li title="使用 ngSubmit 提交该表单link" class="h2 secondary ng-star-inserted"><a href="guide/forms#submit-the-form-with-ngsubmit">使用 <em>ngSubmit</em> 提交该表单</a></li><li title="切换两个表单区域（额外的奖励）link" class="h2 secondary ng-star-inserted"><a href="guide/forms#toggle-two-form-regions-extra-credit">切换两个表单区域（额外的奖励）</a></li><li title="小结link" class="h2 secondary ng-star-inserted"><a href="guide/forms#summary">小结</a></li></ul><button aria-label="Expand/collapse contents" class="toc-more-items embedded material-icons collapsed ng-star-inserted" title="Expand/collapse contents" type="button" aria-pressed="false"></button></div></aio-toc><h1 translation-origin="off" id="template-driven-forms">Template-driven forms<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#template-driven-forms"><i class="material-icons">link</i></a></h1><p translation-result="on">表单是商业应用的支柱，你用它来执行登录、求助、下单、预订机票、安排会议，以及不计其数的其它数据录入任务。</p><p translation-origin="off">Forms are the mainstay of business applications. You use forms to log in, submit a help request, place an order, book a flight, schedule a meeting, and perform countless other data-entry tasks.</p><p translation-result="on">在开发表单时，创建数据方面的体验是非常重要的，它能指引用户明晰、高效的完成工作流程。</p><p translation-origin="off">In developing a form, it's important to create a data-entry experience that guides the user efficiently and effectively through the workflow.</p><h2 id="introduction-to-template-driven-forms" translation-result="on">模板驱动表单简介<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#introduction-to-template-driven-forms"><i class="material-icons">link</i></a></h2><h2 translation-origin="off" id="introduction-to-template-driven-forms">Introduction to Template-driven forms<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#introduction-to-template-driven-forms"><i class="material-icons">link</i></a></h2><p translation-result="on">开发表单需要设计能力（那超出了本章的范围），而框架支持<em>双向数据绑定、变更检测、验证和错误处理</em>，而本章你将会学到它们。</p><p translation-origin="off">Developing forms requires design skills (which are out of scope for this page), as well as framework support for <em>two-way data binding, change tracking, validation, and error handling</em>, which you'll learn about on this page.</p><p translation-result="on">这个页面演示了如何从草稿构建一个简单的表单。这个过程中你将学会如何：</p><p translation-origin="off">This page shows you how to build a simple form from scratch. Along the way you'll learn how to:</p><ul><li><p translation-result="on">用组件和模板构建 Angular 表单</p><p translation-origin="off">Build an Angular form with a component and template.</p></li><li><p translation-result="on">用 <code><a href="api/forms/NgModel" class="code-anchor">ngModel</a></code> 创建双向数据绑定，以读取和写入输入控件的值</p><p translation-origin="off">Use <code><a href="api/forms/NgModel" class="code-anchor">ngModel</a></code> to create two-way data bindings for reading and writing input-control values.</p></li><li><p translation-result="on">跟踪状态的变化，并验证表单控件</p><p translation-origin="off">Track state changes and the validity of form controls.</p></li><li><p translation-result="on">使用特殊的 CSS 类来跟踪控件的状态并给出视觉反馈</p><p translation-origin="off">Provide visual feedback using special CSS classes that track the state of the controls.</p></li><li><p translation-result="on">向用户显示验证错误提示，以及启用/禁用表单控件</p><p translation-origin="off">Display validation errors to users and enable/disable form controls.</p></li><li><p translation-result="on">使用模板引用变量在 HTML 元素之间共享信息</p><p translation-origin="off">Share information across HTML elements using template reference variables.</p></li></ul><p translation-result="on">你可以运行<live-example ng-version="7.0.0"><span style="display:none"></span><span><span class="ng-star-inserted"><a target="_blank" href="generated/live-examples/forms/stackblitz.html" title="在线例子">在线例子</a><span class="ng-star-inserted"> / <a download="" title="下载范例" href="generated/zips/forms/forms.zip">下载范例</a></span></span></span></live-example>，在 Stackblitz 中试用并下载本页的代码。</p><p translation-origin="off">You can run the<live-example ng-version="7.0.0"><span style="display:none"></span><span><span class="ng-star-inserted"><a target="_blank" href="generated/live-examples/forms/stackblitz.html" title="在线例子">在线例子</a><span class="ng-star-inserted"> / <a download="" title="下载范例" href="generated/zips/forms/forms.zip">下载范例</a></span></span></span></live-example>in Stackblitz and download the code from there.</p><a id="template-driven"></a><h2 id="template-driven-forms-1" translation-result="on">模板驱动表单<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#template-driven-forms-1"><i class="material-icons">link</i></a></h2><h2 translation-origin="off" id="template-driven-forms-1">Template-driven forms<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#template-driven-forms-1"><i class="material-icons">link</i></a></h2><p translation-result="on">通常，使用 Angular <a href="guide/template-syntax">模板语法</a>编写模板，结合本章所描述的表单专用指令和技术来构建表单。</p><p translation-origin="off">You can build forms by writing templates in the Angular <a href="guide/template-syntax">template syntax</a> with the form-specific directives and techniques described in this page.</p><div class="alert is-helpful"><p translation-result="on">你还可以使用响应式（也叫模型驱动）的方式来构建表单。不过本章中只介绍模板驱动表单。</p><p translation-origin="off">You can also use a reactive (or model-driven) approach to build forms. However, this page focuses on template-driven forms.</p></div><p translation-result="on">利用 Angular 模板，可以构建几乎所有表单 — 登录表单、联系人表单…… 以及任何的商务表单。 可以创造性地摆放各种控件、把它们绑定到数据、指定校验规则、显示校验错误、有条件的禁用或 启用特定的控件、触发内置的视觉反馈等等，不胜枚举。</p><p translation-origin="off">You can build almost any form with an Angular template—login forms, contact forms, and pretty much any business form. You can lay out the controls creatively, bind them to data, specify validation rules and display validation errors, conditionally enable or disable specific controls, trigger built-in visual feedback, and much more.</p><p translation-result="on">它用起来很简单，这是因为 Angular 处理了大多数重复、单调的任务，这让你可以不必亲自操刀、身陷其中。</p><p translation-origin="off">Angular makes the process easy by handling many of the repetitive, boilerplate tasks you'd otherwise wrestle with yourself.</p><p translation-result="on">你将学习构建如下的“模板驱动”表单：</p><p translation-origin="off">You'll learn to build a template-driven form that looks like this:</p><figure><img src="generated/images/guide/forms/hero-form-1.png" alt="Clean Form" width="479" height="339"></figure><p translation-result="on">这里是<em>英雄职业介绍所</em>，使用这个表单来维护候选英雄们的个人信息。每个英雄都需要一份工作。 公司的使命就是让合适的英雄去应对恰当的危机！</p><p translation-origin="off">The <em>Hero Employment Agency</em> uses this form to maintain personal information about heroes. Every hero needs a job. It's the company mission to match the right hero with the right crisis.</p><p translation-result="on">表单中的三个字段，其中两个是必填的。必填的字段在左侧有个绿色的竖条，方便用户分辨哪些是必填项。</p><p translation-origin="off">Two of the three fields on this form are required. Required fields have a green bar on the left to make them easy to spot.</p><p translation-result="on">如果删除了英雄的名字，表单就会用醒目的样式把验证错误显示出来。</p><p translation-origin="off">If you delete the hero name, the form displays a validation error in an attention-grabbing style:</p><figure><img src="generated/images/guide/forms/hero-form-2.png" alt="Invalid, Name Required" width="465" height="402"></figure><p translation-result="on">注意，提交按钮被禁用了，而且输入控件左侧的“必填”条从绿色变为了红色。</p><p translation-origin="off">Note that the <em>Submit</em> button is disabled, and the "required" bar to the left of the input control changes from green to red.</p><div class="alert is-helpful"><p translation-result="on">稍后，会使用标准 CSS 来定制“必填”条的颜色和位置。</p><p translation-origin="off">You can customize the colors and location of the "required" bar with standard CSS.</p></div><p translation-result="on">你将一点点构建出此表单：</p><p translation-origin="off">You'll build this form in small steps:</p><ol><li><p translation-result="on">创建 <code>Hero</code> 模型类</p><p translation-origin="off">Create the <code>Hero</code> model class.</p></li><li><p translation-result="on">创建控制此表单的组件。</p><p translation-origin="off">Create the component that controls the form.</p></li><li><p translation-result="on">创建具有初始表单布局的模板。</p><p translation-origin="off">Create a template with the initial form layout.</p></li><li><p translation-result="on">使用 <code><a href="api/forms/NgModel" class="code-anchor">ngModel</a></code> 双向数据绑定语法把数据属性绑定到每个表单输入控件。</p><p translation-origin="off">Bind data properties to each form control using the <code><a href="api/forms/NgModel" class="code-anchor">ngModel</a></code> two-way data-binding syntax.</p></li><li><p translation-result="on">往每个表单输入控件上添加 <code>name</code> 属性 (attribute)。</p><p translation-origin="off">Add a <code>name</code> attribute to each form-input control.</p></li><li><p translation-result="on">添加自定义 CSS 来提供视觉反馈。</p><p translation-origin="off">Add custom CSS to provide visual feedback.</p></li><li><p translation-result="on">显示和隐藏有效性验证的错误信息。</p><p translation-origin="off">Show and hide validation-error messages.</p></li><li><p translation-result="on">使用 <strong>ngSubmit</strong> 处理表单提交。</p><p translation-origin="off">Handle form submission with <em>ngSubmit</em>.</p></li><li><p translation-result="on">禁用此表单的提交按钮，直到表单变为有效。</p><p translation-origin="off">Disable the form’s <em>Submit</em> button until the form is valid.</p></li></ol><h2 id="setup" translation-result="on">准备工作<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#setup"><i class="material-icons">link</i></a></h2><h2 translation-origin="off" id="setup">Setup<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#setup"><i class="material-icons">link</i></a></h2><p translation-result="on">创建一个名为 <code>angular-forms</code> 的新项目：</p><p translation-origin="off">Create a new project named <code>angular-forms</code>:</p><code-example language="sh" class="code-shell" ng-version="7.0.0"><div style="display:none">ng new angular-forms</div><aio-code><pre class="prettyprint lang-sh">      <button class="material-icons copy-button no-print ng-star-inserted" title="Copy code snippet" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">ng new angular</span><span class="pun">-</span><span class="pln">forms</span></code>
    </pre></aio-code></code-example><h2 id="create-the-hero-model-class" translation-result="on">创建 Hero 模型类<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#create-the-hero-model-class"><i class="material-icons">link</i></a></h2><h2 translation-origin="off" id="create-the-hero-model-class">Create the Hero model class<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#create-the-hero-model-class"><i class="material-icons">link</i></a></h2><p translation-result="on">当用户输入表单数据时，需要捕获它们的变化，并更新到模型的实例中。 除非知道模型里有什么，否则无法设计表单的布局。</p><p translation-origin="off">As users enter form data, you'll capture their changes and update an instance of a model. You can't lay out the form until you know what the model looks like.</p><p translation-result="on">最简单的模型是个“属性包”，用来存放应用中一件事物的事实。 这里使用三个必备字段 (<code>id</code>、<code>name</code>、<code>power</code>)，和一个可选字段 (<code>alterEgo</code>，译注：中文含义是第二人格，例如 X 战警中的 Jean / 黑凤凰)。</p><p translation-origin="off">A model can be as simple as a "property bag" that holds facts about a thing of application importance. That describes well the <code>Hero</code> class with its three required fields (<code>id</code>, <code>name</code>, <code>power</code>) and one optional field (<code>alterEgo</code>).</p><p translation-result="on">使用 Angular CLI 命令 <a href="cli/generate"><code>ng generate class</code></a>生成一个名叫 <code>Hero</code> 的新类：</p><p translation-origin="off">Using the Angular CLI command <a href="cli/generate"><code>ng generate class</code></a>, generate a new class named <code>Hero</code>:</p><code-example language="sh" class="code-shell" ng-version="7.0.0"><div style="display:none">ng generate class Hero</div><aio-code><pre class="prettyprint lang-sh">      <button class="material-icons copy-button no-print ng-star-inserted" title="Copy code snippet" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">ng generate class </span><span class="typ">Hero</span></code>
    </pre></aio-code></code-example><p translation-result="on">内容如下：</p><p translation-origin="off">With this content:</p><code-example path="forms/src/app/hero.ts" header="src/app/hero.ts" ng-version="7.0.0"><div style="display:none">export class Hero { constructor( public id: number, public name: string, public power: string, public alterEgo?: string ) { } }</div><header class="ng-star-inserted">src/app/hero.ts</header><aio-code class="headed-code"><pre class="prettyprint lang-">      <button class="material-icons copy-button no-print ng-star-inserted" title="Copy code snippet" aria-label="Copy code snippet from src/app/hero.ts">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Hero</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  </span><span class="kwd">constructor</span><span class="pun">(</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> id</span><span class="pun">:</span><span class="pln"> number</span><span class="pun">,</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> name</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">string</span><span class="pun">,</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> power</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">string</span><span class="pun">,</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> alterEgo</span><span class="pun">?:</span><span class="pln"> </span><span class="kwd">string</span><span class="pln">
  </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">  </span><span class="pun">}</span><span class="pln">

</span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">这是一个少量需求和零行为的贫血模型。对演示来说很完美。</p><p translation-origin="off">It's an anemic model with few requirements and no behavior. Perfect for the demo.</p><p translation-result="on">TypeScript 编译器为每个 <code>public</code> 构造函数参数生成一个公共字段，在创建新的英雄实例时，自动把参数值赋给这些公共字段。</p><p translation-origin="off">The TypeScript compiler generates a public field for each <code>public</code> constructor parameter and automatically assigns the parameter’s value to that field when you create heroes.</p><p translation-result="on"><code>alterEgo</code> 是可选的，调用构造函数时可省略，注意 <code>alterEgo?</code> 中的问号 (?)。</p><p translation-origin="off">The <code>alterEgo</code> is optional, so the constructor lets you omit it; note the question mark (?) in <code>alterEgo?</code>.</p><p translation-result="on">可以这样创建新英雄：</p><p translation-origin="off">You can create a new hero like this:</p><code-example path="forms/src/app/hero-form/hero-form.component.ts" linenums="false" region="SkyDog" ng-version="7.0.0"><div style="display:none">let myHero = new Hero(42, 'SkyDog', 'Fetch any object at any distance', 'Leslie Rollover'); console.log('My hero is called ' + myHero.name); // "My hero is called SkyDog"</div><aio-code><pre class="prettyprint lang-">      <button class="material-icons copy-button no-print ng-star-inserted" title="Copy code snippet" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">let</span><span class="pln"> myHero </span><span class="pun">=</span><span class="pln">  </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Hero</span><span class="pun">(</span><span class="lit">42</span><span class="pun">,</span><span class="pln"> </span><span class="str">'SkyDog'</span><span class="pun">,</span><span class="pln">
                       </span><span class="str">'Fetch any object at any distance'</span><span class="pun">,</span><span class="pln">
                       </span><span class="str">'Leslie Rollover'</span><span class="pun">);</span><span class="pln">
console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">'My hero is called '</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> myHero</span><span class="pun">.</span><span class="pln">name</span><span class="pun">);</span><span class="pln"> </span><span class="com">// "My hero is called SkyDog"</span></code>
    </pre></aio-code></code-example><h2 id="create-a-form-component" translation-result="on">创建表单组件<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#create-a-form-component"><i class="material-icons">link</i></a></h2><h2 translation-origin="off" id="create-a-form-component">Create a form component<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#create-a-form-component"><i class="material-icons">link</i></a></h2><p translation-result="on">Angular 表单分为两部分：基于 HTML 的<em>模板</em>和组件<em>类</em>，用来程序处理数据和用户交互。 先从组件类开始，是因为它可以简要说明英雄编辑器能做什么。</p><p translation-origin="off">An Angular form has two parts: an HTML-based <em>template</em> and a component <em>class</em> to handle data and user interactions programmatically. Begin with the class because it states, in brief, what the hero editor can do.</p><p translation-result="on">使用 Angular CLI 命令 <a href="cli/generate"><code>ng generate class</code></a>生成一个名叫 <code>HeroForm</code> 的新组件：</p><p translation-origin="off">Using the Angular CLI command <a href="cli/generate"><code>ng generate component</code></a>, generate a new component named <code>HeroForm</code>:</p><code-example language="sh" class="code-shell" ng-version="7.0.0"><div style="display:none">ng generate component HeroForm</div><aio-code><pre class="prettyprint lang-sh">      <button class="material-icons copy-button no-print ng-star-inserted" title="Copy code snippet" aria-label="">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">ng generate component </span><span class="typ">HeroForm</span></code>
    </pre></aio-code></code-example><p translation-result="on">内容如下：</p><p translation-origin="off">With this content:</p><code-example path="forms/src/app/hero-form/hero-form.component.ts" linenums="false" header="src/app/hero-form/hero-form.component.ts (v1)" region="v1" ng-version="7.0.0"><div style="display:none">import { <a href="api/core/Component" class="code-anchor">Component</a> } from '@angular/core'; import { Hero } from '../hero'; @<a href="api/core/Component" class="code-anchor">Component</a>({ selector: 'app-hero-form', templateUrl: './hero-form.component.html', <a href="api/core/Component#styleUrls" class="code-anchor">styleUrls</a>: ['./hero-form.component.css'] }) export class HeroFormComponent { powers = ['Really Smart', 'Super Flexible', 'Super Hot', 'Weather Changer']; <a href="api/forms/NgModel#model" class="code-anchor">model</a> = new Hero(18, 'Dr IQ', this.powers[0], 'Chuck Overstreet'); submitted = false; onSubmit() { this.submitted = true; } // TODO: Remove this when we're <a href="api/core/ApplicationInitStatus#done" class="code-anchor">done</a> get diagnostic() { return JSON.stringify(this.model); } }</div><header class="ng-star-inserted">src/app/hero-form/hero-form.component.ts (v1)</header><aio-code class="headed-code"><pre class="prettyprint lang-">      <button class="material-icons copy-button no-print ng-star-inserted" title="Copy code snippet" aria-label="Copy code snippet from src/app/hero-form/hero-form.component.ts (v1)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/Component" class="code-anchor"><span class="typ">Component</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">Hero</span><span class="pln"> </span><span class="pun">}</span><span class="pln">    </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'../hero'</span><span class="pun">;</span><span class="pln">

</span><span class="lit">@</span><a href="api/core/Component" class="code-anchor"><span class="lit">Component</span></a><span class="pun">({</span><span class="pln">
  selector</span><span class="pun">:</span><span class="pln"> </span><span class="str">'app-hero-form'</span><span class="pun">,</span><span class="pln">
  templateUrl</span><span class="pun">:</span><span class="pln"> </span><span class="str">'./hero-form.component.html'</span><span class="pun">,</span><span class="pln">
  </span><a href="api/core/Component#styleUrls" class="code-anchor"><span class="pln">styleUrls</span></a><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="str">'./hero-form.component.css'</span><span class="pun">]</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">HeroFormComponent</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  powers </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'Really Smart'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Super Flexible'</span><span class="pun">,</span><span class="pln">
            </span><span class="str">'Super Hot'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Weather Changer'</span><span class="pun">];</span><span class="pln">

  </span><a href="api/forms/NgModel#model" class="code-anchor"><span class="pln">model</span></a><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Hero</span><span class="pun">(</span><span class="lit">18</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Dr IQ'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">powers</span><span class="pun">[</span><span class="lit">0</span><span class="pun">],</span><span class="pln"> </span><span class="str">'Chuck Overstreet'</span><span class="pun">);</span><span class="pln">

  submitted </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">

  onSubmit</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">submitted </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

  </span><span class="com">// TODO: Remove this when we're </span><a href="api/core/ApplicationInitStatus#done" class="code-anchor"><span class="com">done</span></a><span class="pln">
  </span><span class="kwd">get</span><span class="pln"> diagnostic</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> JSON</span><span class="pun">.</span><span class="pln">stringify</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">model</span><span class="pun">);</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">这个组件没有什么特别的地方，没有表单相关的东西，与之前写过的组件没什么不同。</p><p translation-origin="off">There’s nothing special about this component, nothing form-specific, nothing to distinguish it from any component you've written before.</p><p translation-result="on">只要用前面章节中学过的 Angular 概念，就可以完全理解这个组件：</p><p translation-origin="off">Understanding this component requires only the Angular concepts covered in previous pages.</p><ul><li><p translation-result="on">这段代码导入了 Angular 核心库以及你刚刚创建的 <code>Hero</code> 模型。</p><p translation-origin="off">The code imports the Angular core library and the <code>Hero</code> model you just created.</p></li><li><p translation-result="on"> <code>@<a href="api/core/Component" class="code-anchor">Component</a></code> 选择器“hero-form”表示可以用 <code>&lt;app-hero-form&gt;</code> 标签把这个表单放进父模板。</p><p translation-origin="off">The <code>@<a href="api/core/Component" class="code-anchor">Component</a></code> selector value of "app-hero-form" means you can drop this form in a parent template with a <code>&lt;app-hero-form&gt;</code> tag.</p></li><li><p translation-result="on"> <code>templateUrl</code> 属性指向一个独立的 HTML 模板文件。</p><p translation-origin="off">The <code>templateUrl</code> property points to a separate file for the template HTML.</p></li><li><p translation-result="on">你定义了一些用来演示的，关于 <code><a href="api/forms/NgModel#model" class="code-anchor">model</a></code> 和 <code>powers</code> 的模拟数据。</p><p translation-origin="off">You defined dummy data for <code><a href="api/forms/NgModel#model" class="code-anchor">model</a></code> and <code>powers</code>, as befits a demo.</p></li></ul><p translation-result="on">接下来，你可以注入一个数据服务，以获取或保存真实的数据，或者把这些属性暴露为输入属性和输出属性（参见<a href="guide/template-syntax">Template Syntax</a>中的<a href="guide/template-syntax#inputs-outputs">输入和输出属性</a>）来绑定到一个父组件。这不是现在需要关心的问题，未来的更改不会影响到这个表单。</p><p translation-origin="off">Down the road, you can inject a data service to get and save real data or perhaps expose these properties as inputs and outputs (see <a href="guide/template-syntax#inputs-outputs">Input and output properties</a> on the <a href="guide/template-syntax">Template Syntax</a> page) for binding to a parent component. This is not a concern now and these future changes won't affect the form.</p><ul><li><p translation-result="on">你添加一个 <code>diagnostic</code> 属性，以返回这个模型的 JSON 形式。在开发过程中，它用于调试，最后清理时会丢弃它。</p><p translation-origin="off">You added a <code>diagnostic</code> property to return a JSON representation of the model. It'll help you see what you're doing during development; you've left yourself a cleanup note to discard it later.</p></li></ul><h2 id="revise-appmodulets" translation-result="on">修改 <em>app.module.ts</em><a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#revise-appmodulets"><i class="material-icons">link</i></a></h2><h2 translation-origin="off" id="revise-appmodulets">Revise <em>app.module.ts</em><a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#revise-appmodulets"><i class="material-icons">link</i></a></h2><p translation-result="on"><code>app.module.ts</code> 定义了应用的根模块。其中标识即将用到的外部模块，以及声明属于本模块中的组件，例如 <code>HeroFormComponent</code>。</p><p translation-origin="off"><code>app.module.ts</code> defines the application's root module. In it you identify the external modules you'll use in the application and declare the components that belong to this module, such as the <code>HeroFormComponent</code>.</p><p translation-result="on">因为模板驱动的表单位于它们自己的模块，所以在使用表单之前，需要将 <code><a href="api/forms/FormsModule" class="code-anchor">FormsModule</a></code> 添加到应用模块的 <code><a href="api/core/NgModule#imports" class="code-anchor">imports</a></code> 数组中。</p><p translation-origin="off">Because template-driven forms are in their own module, you need to add the <code><a href="api/forms/FormsModule" class="code-anchor">FormsModule</a></code> to the array of <code><a href="api/core/NgModule#imports" class="code-anchor">imports</a></code> for the application module before you can use forms.</p><p translation-result="on">对它做如下修改：</p><p translation-origin="off">Update it with the following:</p><code-example path="forms/src/app/app.module.ts" header="src/app/app.module.ts" ng-version="7.0.0"><div style="display:none">import { <a href="api/core/NgModule" class="code-anchor">NgModule</a> } from '@angular/core'; import { <a href="api/platform-browser/BrowserModule" class="code-anchor">BrowserModule</a> } from '@angular/platform-browser'; import { <a href="api/forms/FormsModule" class="code-anchor">FormsModule</a> } from '@angular/forms'; import { AppComponent } from './app.component'; import { HeroFormComponent } from './hero-form/hero-form.component'; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ <a href="api/core/NgModule#imports" class="code-anchor">imports</a>: [ <a href="api/platform-browser/BrowserModule" class="code-anchor">BrowserModule</a>, <a href="api/forms/FormsModule" class="code-anchor">FormsModule</a> ], <a href="api/core/NgModule#declarations" class="code-anchor">declarations</a>: [ AppComponent, HeroFormComponent ], providers: [], <a href="api/core/NgModule#bootstrap" class="code-anchor">bootstrap</a>: [ AppComponent ] }) export class AppModule { }</div><header class="ng-star-inserted">src/app/app.module.ts</header><aio-code class="headed-code"><pre class="prettyprint lang-">      <button class="material-icons copy-button no-print ng-star-inserted" title="Copy code snippet" aria-label="Copy code snippet from src/app/app.module.ts">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><ol class="linenums"><li class="L0"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/NgModule" class="code-anchor"><span class="typ">NgModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">      </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span></li><li class="L1"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/platform-browser/BrowserModule" class="code-anchor"><span class="typ">BrowserModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/platform-browser'</span><span class="pun">;</span></li><li class="L2"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/forms/FormsModule" class="code-anchor"><span class="typ">FormsModule</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln">   </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/forms'</span><span class="pun">;</span></li><li class="L3"><span class="pln">&nbsp;</span></li><li class="L4"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">AppComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln">  </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./app.component'</span><span class="pun">;</span></li><li class="L5"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">HeroFormComponent</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'./hero-form/hero-form.component'</span><span class="pun">;</span></li><li class="L6"><span class="pln">&nbsp;</span></li><li class="L7"><span class="lit">@</span><a href="api/core/NgModule" class="code-anchor"><span class="lit">NgModule</span></a><span class="pun">({</span></li><li class="L8"><span class="pln">  </span><a href="api/core/NgModule#imports" class="code-anchor"><span class="pln">imports</span></a><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span></li><li class="L9"><span class="pln">    </span><a href="api/platform-browser/BrowserModule" class="code-anchor"><span class="typ">BrowserModule</span></a><span class="pun">,</span></li><li class="L0"><span class="pln">    </span><a href="api/forms/FormsModule" class="code-anchor"><span class="typ">FormsModule</span></a></li><li class="L1"><span class="pln">  </span><span class="pun">],</span></li><li class="L2"><span class="pln">  </span><a href="api/core/NgModule#declarations" class="code-anchor"><span class="pln">declarations</span></a><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span></li><li class="L3"><span class="pln">    </span><span class="typ">AppComponent</span><span class="pun">,</span></li><li class="L4"><span class="pln">    </span><span class="typ">HeroFormComponent</span></li><li class="L5"><span class="pln">  </span><span class="pun">],</span></li><li class="L6"><span class="pln">  providers</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[],</span></li><li class="L7"><span class="pln">  </span><a href="api/core/NgModule#bootstrap" class="code-anchor"><span class="pln">bootstrap</span></a><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> </span><span class="typ">AppComponent</span><span class="pln"> </span><span class="pun">]</span></li><li class="L8"><span class="pun">})</span></li><li class="L9"><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">AppModule</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span></li></ol></code>
    </pre></aio-code></code-example><div class="alert is-helpful"><p translation-result="on">有两处更改</p><p translation-origin="off">There are two changes:</p><ol><li><p translation-result="on">导入 <code><a href="api/forms/FormsModule" class="code-anchor">FormsModule</a></code>。</p><p translation-origin="off">You import <code><a href="api/forms/FormsModule" class="code-anchor">FormsModule</a></code>.</p></li><li><p translation-result="on">把 <code><a href="api/forms/FormsModule" class="code-anchor">FormsModule</a></code> 添加到 <code>ngModule</code> 装饰器的 <code><a href="api/core/NgModule#imports" class="code-anchor">imports</a></code> 列表中，这样应用就能访问模板驱动表单的所有特性，包括 <code><a href="api/forms/NgModel" class="code-anchor">ngModel</a></code>。</p><p translation-origin="off">You add the <code><a href="api/forms/FormsModule" class="code-anchor">FormsModule</a></code> to the list of <code><a href="api/core/NgModule#imports" class="code-anchor">imports</a></code> defined in the <code>@<a href="api/core/NgModule" class="code-anchor">NgModule</a></code> decorator. This gives the application access to all of the template-driven forms features, including <code><a href="api/forms/NgModel" class="code-anchor">ngModel</a></code>.</p></li></ol></div><div class="alert is-important"><p translation-result="on">如果某个组件、指令或管道是属于 <code><a href="api/core/NgModule#imports" class="code-anchor">imports</a></code> 中所导入的某个模块的，那就<em>不能再</em>把它再声明到本模块的 <code><a href="api/core/NgModule#declarations" class="code-anchor">declarations</a></code> 数组中。 如果它是你自己写的，并且确实属于当前模块，<em>才应该</em>把它声明在 <code><a href="api/core/NgModule#declarations" class="code-anchor">declarations</a></code> 数组中。</p><p translation-origin="off">If a component, directive, or pipe belongs to a module in the <code><a href="api/core/NgModule#imports" class="code-anchor">imports</a></code> array, ​<em>don't</em>​ re-declare it in the <code><a href="api/core/NgModule#declarations" class="code-anchor">declarations</a></code> array. If you wrote it and it should belong to this module, ​<em>do</em>​ declare it in the <code><a href="api/core/NgModule#declarations" class="code-anchor">declarations</a></code> array.</p></div><h2 id="revise-appcomponenthtml" translation-result="on">修改 <em>app.component.ts</em><a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#revise-appcomponenthtml"><i class="material-icons">link</i></a></h2><h2 translation-origin="off" id="revise-appcomponenthtml">Revise <em>app.component.html</em><a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#revise-appcomponenthtml"><i class="material-icons">link</i></a></h2><p translation-result="on"><code>AppComponent</code> 是应用的根组件，<code>HeroFormComponent</code> 将被放在其中。</p><p translation-origin="off"><code>AppComponent</code> is the application's root component. It will host the new <code>HeroFormComponent</code>.</p><p translation-result="on">把模板中的内容替换成如下代码：</p><p translation-origin="off">Replace the contents of its template with the following:</p><code-example path="forms/src/app/app.component.html" header="src/app/app.component.html" ng-version="7.0.0"><div style="display:none">&lt;app-hero-form&gt;&lt;/app-hero-form&gt;</div><header class="ng-star-inserted">src/app/app.component.html</header><aio-code class="headed-code"><pre class="prettyprint lang-">      <button class="material-icons copy-button no-print ng-star-inserted" title="Copy code snippet" aria-label="Copy code snippet from src/app/app.component.html">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;app-hero-form&gt;&lt;/app-hero-form&gt;</span></code>
    </pre></aio-code></code-example><div class="alert is-helpful"><p translation-result="on">这里只做了两处修改。 <code><a href="api/core/Component#template" class="code-anchor">template</a></code> 中只剩下这个新的元素标签，即组件的 <code>selector</code> 属性。这样当应用组件被加载时，就会显示这个英雄表单。 同样别忘了从类中移除了 <code>name</code> 字段。</p><p translation-origin="off">There are only two changes. The <code><a href="api/core/Component#template" class="code-anchor">template</a></code> is simply the new element tag identified by the component's <code>selector</code> property. This displays the hero form when the application component is loaded. Don't forget to remove the <code>name</code> field from the class body as well.</p></div><h2 id="create-an-initial-html-form-template" translation-result="on">创建初始 HTML 表单模板<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#create-an-initial-html-form-template"><i class="material-icons">link</i></a></h2><h2 translation-origin="off" id="create-an-initial-html-form-template">Create an initial HTML form template<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#create-an-initial-html-form-template"><i class="material-icons">link</i></a></h2><p translation-result="on">修改模板文件，内容如下：</p><p translation-origin="off">Update the template file with the following contents:</p><code-example path="forms/src/app/hero-form/hero-form.component.html" region="start" header="src/app/hero-form/hero-form.component.html" ng-version="7.0.0"><div style="display:none">&lt;div class="container"&gt; &lt;h1&gt;Hero <a href="api/forms/Form" class="code-anchor">Form</a>&lt;/h1&gt; &lt;form&gt; &lt;div class="form-group"&gt; &lt;label for="name"&gt;Name&lt;/label&gt; &lt;input type="text" class="form-control" id="name" required&gt; &lt;/div&gt; &lt;div class="form-group"&gt; &lt;label for="alterEgo"&gt;Alter Ego&lt;/label&gt; &lt;input type="text" class="form-control" id="alterEgo"&gt; &lt;/div&gt; &lt;button type="submit" class="btn btn-success"&gt;Submit&lt;/button&gt; &lt;/form&gt; &lt;/div&gt;</div><header class="ng-star-inserted">src/app/hero-form/hero-form.component.html</header><aio-code class="headed-code"><pre class="prettyprint lang-">      <button class="material-icons copy-button no-print ng-star-inserted" title="Copy code snippet" aria-label="Copy code snippet from src/app/hero-form/hero-form.component.html">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><ol class="linenums"><li class="L0"><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"container"</span><span class="tag">&gt;</span></li><li class="L1"><span class="pln">    </span><span class="tag">&lt;h1&gt;</span><span class="pln">Hero </span><a href="api/forms/Form" class="code-anchor"><span class="pln">Form</span></a><span class="tag">&lt;/h1&gt;</span></li><li class="L2"><span class="pln">    </span><span class="tag">&lt;form&gt;</span></li><li class="L3"><span class="pln">      </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"form-group"</span><span class="tag">&gt;</span></li><li class="L4"><span class="pln">        </span><span class="tag">&lt;label</span><span class="pln"> </span><span class="atn">for</span><span class="pun">=</span><span class="atv">"name"</span><span class="tag">&gt;</span><span class="pln">Name</span><span class="tag">&lt;/label&gt;</span></li><li class="L5"><span class="pln">        </span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"text"</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"form-control"</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"name"</span><span class="pln"> </span><span class="atn">required</span><span class="tag">&gt;</span></li><li class="L6"><span class="pln">      </span><span class="tag">&lt;/div&gt;</span></li><li class="L7"><span class="pln">&nbsp;</span></li><li class="L8"><span class="pln">      </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"form-group"</span><span class="tag">&gt;</span></li><li class="L9"><span class="pln">        </span><span class="tag">&lt;label</span><span class="pln"> </span><span class="atn">for</span><span class="pun">=</span><span class="atv">"alterEgo"</span><span class="tag">&gt;</span><span class="pln">Alter Ego</span><span class="tag">&lt;/label&gt;</span></li><li class="L0"><span class="pln">        </span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"text"</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"form-control"</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"alterEgo"</span><span class="tag">&gt;</span></li><li class="L1"><span class="pln">      </span><span class="tag">&lt;/div&gt;</span></li><li class="L2"><span class="pln">&nbsp;</span></li><li class="L3"><span class="pln">      </span><span class="tag">&lt;button</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"submit"</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"btn btn-success"</span><span class="tag">&gt;</span><span class="pln">Submit</span><span class="tag">&lt;/button&gt;</span></li><li class="L4"><span class="pln">&nbsp;</span></li><li class="L5"><span class="pln">    </span><span class="tag">&lt;/form&gt;</span></li><li class="L6"><span class="tag">&lt;/div&gt;</span></li></ol></code>
    </pre></aio-code></code-example><p translation-result="on">这只是一段普通的旧式 HTML 5 代码。这里有两个 <code>Hero</code> 字段，<code>name</code> 和 <code>alterEgo</code>，供用户输入。</p><p translation-origin="off">The language is simply HTML5. You're presenting two of the <code>Hero</code> fields, <code>name</code> and <code>alterEgo</code>, and opening them up for user input in input boxes.</p><p translation-result="on"><em>Name</em> <code>&lt;input&gt;</code> 控件具有 HTML5 的 <code>required</code> 属性；但 <em>Alter Ego</em> <code>&lt;input&gt;</code> 控件没有，因为 <code>alterEgo</code> 字段是可选的。</p><p translation-origin="off">The <em>Name</em> <code>&lt;input&gt;</code> control has the HTML5 <code>required</code> attribute; the <em>Alter Ego</em> <code>&lt;input&gt;</code> control does not because <code>alterEgo</code> is optional.</p><p translation-result="on">在底部添加个 <em>Submit</em> 按钮，它还带一些 CSS 样式类。</p><p translation-origin="off">You added a <em>Submit</em> button at the bottom with some classes on it for styling.</p><p translation-result="on"><strong>你还没有真正用到 Angular</strong>。没有绑定，没有额外的指令，只有布局。</p><p translation-origin="off"><em>You're not using Angular yet</em>. There are no bindings or extra directives, just layout.</p><div class="alert is-helpful"><p translation-result="on">在模板驱动表单中，你只要导入了 <code><a href="api/forms/FormsModule" class="code-anchor">FormsModule</a></code> 就不用对 <code>&lt;form&gt;</code> 做任何改动来使用 <code><a href="api/forms/FormsModule" class="code-anchor">FormsModule</a></code>。接下来你会看到它的原理。</p><p translation-origin="off">In template driven forms, if you've imported <code><a href="api/forms/FormsModule" class="code-anchor">FormsModule</a></code>, you don't have to do anything to the <code>&lt;form&gt;</code> tag in order to make use of <code><a href="api/forms/FormsModule" class="code-anchor">FormsModule</a></code>. Continue on to see how this works.</p></div><p translation-result="on"><code>container</code>、<code>form-group</code>、<code>form-control</code> 和 <code>btn</code> 类来自 <a href="http://getbootstrap.com/css/">Twitter Bootstrap</a>。这些类纯粹是装饰品。 Bootstrap 为这个表单提供了一些样式。</p><p translation-origin="off">The <code>container</code>, <code>form-group</code>, <code>form-control</code>, and <code>btn</code> classes come from <a href="http://getbootstrap.com/css/">Twitter Bootstrap</a>. These classes are purely cosmetic. Bootstrap gives the form a little style.</p><div class="callout is-important"><header translation-result="on">Angular 表单不需要任何样式库</header><header translation-origin="off">Angular forms don't require a style library</header><p translation-result="on">Angular 不需要 <code>container</code>、<code>form-group</code>、<code>form-control</code> 和 <code>btn</code> 类， 或者外部库的任何样式。Angular 应用可以使用任何 CSS 库…… ，或者啥都不用。</p><p translation-origin="off">Angular makes no use of the <code>container</code>, <code>form-group</code>, <code>form-control</code>, and <code>btn</code> classes or the styles of any external library. Angular apps can use any CSS library or none at all.</p></div><p translation-result="on">要添加样式表，就打开 <code>styles.css</code>，并把下列代码添加到顶部：</p><p translation-origin="off">To add the stylesheet, open <code>styles.css</code> and add the following import line at the top:</p><code-example path="forms/src/styles.1.css" linenums="false" header="src/styles.css" ng-version="7.0.0"><div style="display:none">@import url('https://unpkg.com/<a href="api/core/NgModule#bootstrap" class="code-anchor">bootstrap</a>@3.3.7/dist/css/bootstrap.min.css');</div><header class="ng-star-inserted">src/styles.css</header><aio-code class="headed-code"><pre class="prettyprint lang-">      <button class="material-icons copy-button no-print ng-star-inserted" title="Copy code snippet" aria-label="Copy code snippet from src/styles.css">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="lit">@import</span><span class="pln"> url</span><span class="pun">(</span><span class="str">'https://unpkg.com/</span><a href="api/core/NgModule#bootstrap" class="code-anchor"><span class="str">bootstrap</span></a><span class="str">@3.3.7/dist/css/bootstrap.min.css'</span><span class="pun">);</span></code>
    </pre></aio-code></code-example><h2 id="add-powers-with-ngfor" translation-result="on">用 <strong><em>ngFor</em></strong> 添加超能力<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#add-powers-with-ngfor"><i class="material-icons">link</i></a></h2><h2 translation-origin="off" id="add-powers-with-ngfor">Add powers with <em>*ngFor</em><a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#add-powers-with-ngfor"><i class="material-icons">link</i></a></h2><p translation-result="on">英雄必须从认证过的固定列表中选择一项超能力。 这个列表位于 <code>HeroFormComponent</code> 中。</p><p translation-origin="off">The hero must choose one superpower from a fixed list of agency-approved powers. You maintain that list internally (in <code>HeroFormComponent</code>).</p><p translation-result="on">在表单中添加 <code>select</code>，用 <code><a href="api/common/NgForOf" class="code-anchor">ngFor</a></code> 把 <code>powers</code> 列表绑定到列表选项。 之前的<a href="guide/displaying-data">显示数据</a>一章中见过 <code><a href="api/common/NgForOf" class="code-anchor">ngFor</a></code>。</p><p translation-origin="off">You'll add a <code>select</code> to the form and bind the options to the <code>powers</code> list using <code><a href="api/common/NgForOf" class="code-anchor">ngFor</a></code>, a technique seen previously in the <a href="guide/displaying-data">Displaying Data</a> page.</p><p translation-result="on">在 <em>Alter Ego</em> 的紧下方添加如下 HTML：</p><p translation-origin="off">Add the following HTML <em>immediately below</em> the <em>Alter Ego</em> group:</p><code-example path="forms/src/app/hero-form/hero-form.component.html" linenums="false" header="src/app/hero-form/hero-form.component.html (powers)" region="powers" ng-version="7.0.0"><div style="display:none">&lt;div class="form-group"&gt; &lt;label for="power"&gt;Hero Power&lt;/label&gt; &lt;select class="form-control" id="power" required&gt; &lt;<a href="api/forms/NgSelectOption" class="code-anchor">option</a> *<a href="api/common/NgForOf" class="code-anchor">ngFor</a>="let pow of powers" [value]="pow"&gt;{{pow}}&lt;/<a href="api/forms/NgSelectOption" class="code-anchor">option</a>&gt; &lt;/select&gt; &lt;/div&gt;</div><header class="ng-star-inserted">src/app/hero-form/hero-form.component.html (powers)</header><aio-code class="headed-code"><pre class="prettyprint lang-">      <button class="material-icons copy-button no-print ng-star-inserted" title="Copy code snippet" aria-label="Copy code snippet from src/app/hero-form/hero-form.component.html (powers)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"form-group"</span><span class="tag">&gt;</span><span class="pln">
  </span><span class="tag">&lt;label</span><span class="pln"> </span><span class="atn">for</span><span class="pun">=</span><span class="atv">"power"</span><span class="tag">&gt;</span><span class="pln">Hero Power</span><span class="tag">&lt;/label&gt;</span><span class="pln">
  </span><span class="tag">&lt;select</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"form-control"</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"power"</span><span class="pln"> </span><span class="atn">required</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;</span><a href="api/forms/NgSelectOption" class="code-anchor"><span class="tag">option</span></a><span class="pln"> *</span><a href="api/common/NgForOf" class="code-anchor"><span class="atn">ngFor</span></a><span class="pun">=</span><span class="atv">"let pow of powers"</span><span class="pln"> [</span><span class="atn">value</span><span class="pln">]</span><span class="pun">=</span><span class="atv">"pow"</span><span class="tag">&gt;</span><span class="pln">{{pow}}</span><span class="tag">&lt;/</span><a href="api/forms/NgSelectOption" class="code-anchor"><span class="tag">option</span></a><span class="tag">&gt;</span><span class="pln">
  </span><span class="tag">&lt;/select&gt;</span><span class="pln">
</span><span class="tag">&lt;/div&gt;</span></code>
    </pre></aio-code></code-example><p translation-result="on">列表中的每一项超能力都会渲染成 <code>&lt;<a href="api/forms/NgSelectOption" class="code-anchor">option</a>&gt;</code> 标签。 模板输入变量 <code>pow</code> 在每个迭代指向不同的超能力，使用双花括号插值表达式语法来显示它的名称。</p><p translation-origin="off">This code repeats the <code>&lt;<a href="api/forms/NgSelectOption" class="code-anchor">option</a>&gt;</code> tag for each power in the list of powers. The <code>pow</code> template input variable is a different power in each iteration; you display its name using the interpolation syntax.</p><a id="ngModel"></a><h2 id="two-way-data-binding-with-ngmodel" translation-result="on">使用 <em>ngModel</em> 进行双向数据绑定<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#two-way-data-binding-with-ngmodel"><i class="material-icons">link</i></a></h2><h2 translation-origin="off" id="two-way-data-binding-with-ngmodel">Two-way data binding with <em>ngModel</em><a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#two-way-data-binding-with-ngmodel"><i class="material-icons">link</i></a></h2><p translation-result="on">如果立即运行此应用，你将会失望。</p><p translation-origin="off">Running the app right now would be disappointing.</p><figure><img src="generated/images/guide/forms/hero-form-3.png" alt="Early form with no binding" width="473" height="294"></figure><p translation-result="on">因为还没有绑定到某个英雄，所以看不到任何数据。 解决方案见前面的章节。 <a href="guide/displaying-data">显示数据</a>介绍了属性绑定。 <a href="guide/user-input">用户输入</a>介绍了如何通过事件绑定来监听 DOM 事件，以及如何用显示值更新组件的属性。</p><p translation-origin="off">You don't see hero data because you're not binding to the <code>Hero</code> yet. You know how to do that from earlier pages. <a href="guide/displaying-data">Displaying Data</a> teaches property binding. <a href="guide/user-input">User Input</a> shows how to listen for DOM events with an event binding and how to update a component property with the displayed value.</p><p translation-result="on">现在，需要同时进行显示、监听和提取。</p><p translation-origin="off">Now you need to display, listen, and extract at the same time.</p><p translation-result="on">虽然可以在表单中再次使用这些技术。 但是，这里将介绍个新东西，<code>[(<a href="api/forms/NgModel" class="code-anchor">ngModel</a>)]</code> 语法，使表单绑定到模型的工作变得超级简单。</p><p translation-origin="off">You could use the techniques you already know, but instead you'll use the new <code>[(<a href="api/forms/NgModel" class="code-anchor">ngModel</a>)]</code> syntax, which makes binding the form to the model easy.</p><p translation-result="on">找到 <em>Name</em> 对应的 <code>&lt;input&gt;</code> 标签，并且像这样修改它：</p><p translation-origin="off">Find the <code>&lt;input&gt;</code> tag for <em>Name</em> and update it like this:</p><code-example path="forms/src/app/hero-form/hero-form.component.html" linenums="false" header="src/app/hero-form/hero-form.component.html (excerpt)" region="ngModelName-1" ng-version="7.0.0"><div style="display:none">&lt;input type="text" class="form-control" id="name" required [(<a href="api/forms/NgModel" class="code-anchor">ngModel</a>)]="model.name" name="name"&gt; TODO: remove this: {{model.name}}</div><header class="ng-star-inserted">src/app/hero-form/hero-form.component.html (excerpt)</header><aio-code class="headed-code"><pre class="prettyprint lang-">      <button class="material-icons copy-button no-print ng-star-inserted" title="Copy code snippet" aria-label="Copy code snippet from src/app/hero-form/hero-form.component.html (excerpt)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"text"</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"form-control"</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"name"</span><span class="pln">
       </span><span class="atn">required</span><span class="pln">
       [(</span><a href="api/forms/NgModel" class="code-anchor"><span class="atn">ngModel</span></a><span class="pln">)]</span><span class="pun">=</span><span class="atv">"model.name"</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"name"</span><span class="tag">&gt;</span><span class="pln">
TODO: remove this: {{model.name}}</span></code>
    </pre></aio-code></code-example><div class="alert is-helpful"><p translation-result="on">在 input 标签后添加用于诊断的插值表达式，以看清正在发生什么事。 给自己留个备注，提醒你完成后移除它。</p><p translation-origin="off">You added a diagnostic interpolation after the input tag so you can see what you're doing. You left yourself a note to throw it away when you're done.</p></div><p translation-result="on">聚焦到绑定语法 <code>[(<a href="api/forms/NgModel" class="code-anchor">ngModel</a>)]="..."</code> 上。</p><p translation-origin="off">Focus on the binding syntax: <code>[(<a href="api/forms/NgModel" class="code-anchor">ngModel</a>)]="..."</code>.</p><p translation-result="on">你需要更多的工作来显示数据。在表单中声明一个模板变量。往 <code>&lt;form&gt;</code> 标签中加入 <code>#heroForm="<a href="api/forms/NgForm" class="code-anchor">ngForm</a>"</code>，代码如下：</p><p translation-origin="off">You need one more addition to display the data. Declare a template variable for the form. Update the <code>&lt;form&gt;</code> tag with <code>#heroForm="<a href="api/forms/NgForm" class="code-anchor">ngForm</a>"</code> as follows:</p><code-example path="forms/src/app/hero-form/hero-form.component.html" linenums="false" header="src/app/hero-form/hero-form.component.html (excerpt)" region="template-variable" ng-version="7.0.0"><div style="display:none">&lt;form #heroForm="<a href="api/forms/NgForm" class="code-anchor">ngForm</a>"&gt;</div><header class="ng-star-inserted">src/app/hero-form/hero-form.component.html (excerpt)</header><aio-code class="headed-code"><pre class="prettyprint lang-">      <button class="material-icons copy-button no-print ng-star-inserted" title="Copy code snippet" aria-label="Copy code snippet from src/app/hero-form/hero-form.component.html (excerpt)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;form</span><span class="pln"> #</span><span class="atn">heroForm</span><span class="pun">=</span><span class="atv">"</span><a href="api/forms/NgForm" class="code-anchor"><span class="atv">ngForm</span></a><span class="atv">"</span><span class="tag">&gt;</span></code>
    </pre></aio-code></code-example><p translation-result="on"><code>heroForm</code> 变量是一个到 <code><a href="api/forms/NgForm" class="code-anchor">NgForm</a></code> 指令的引用，它代表该表单的整体。</p><p translation-origin="off">The variable <code>heroForm</code> is now a reference to the <code><a href="api/forms/NgForm" class="code-anchor">NgForm</a></code> directive that governs the form as a whole.</p><div class="alert is-helpful"><p><a id="ngForm"></a></p><h3 id="the-ngform-directive" translation-result="on"><em>NgForm</em> 指令<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#the-ngform-directive"><i class="material-icons">link</i></a></h3><h3 translation-origin="off" id="the-ngform-directive">The <em>NgForm</em> directive<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#the-ngform-directive"><i class="material-icons">link</i></a></h3><p translation-result="on">什么是 <code><a href="api/forms/NgForm" class="code-anchor">NgForm</a></code> 指令？ 但你明明没有添加过<a href="api/forms/NgForm">NgForm</a>指令啊！</p><p translation-origin="off">What <code><a href="api/forms/NgForm" class="code-anchor">NgForm</a></code> directive? You didn't add an <a href="api/forms/NgForm">NgForm</a> directive.</p><p translation-result="on">Angular 替你做了。Angular 会在 <code>&lt;form&gt;</code> 标签上自动创建并附加一个 <code><a href="api/forms/NgForm" class="code-anchor">NgForm</a></code> 指令。</p><p translation-origin="off">Angular did. Angular automatically creates and attaches an <code><a href="api/forms/NgForm" class="code-anchor">NgForm</a></code> directive to the <code>&lt;form&gt;</code> tag.</p><p translation-result="on"> <code><a href="api/forms/NgForm" class="code-anchor">NgForm</a></code> 指令为 <code>form</code> 增补了一些额外特性。 它会控制那些带有 <code><a href="api/forms/NgModel" class="code-anchor">ngModel</a></code> 指令和 <code>name</code> 属性的元素，监听他们的属性（包括其有效性）。 它还有自己的 <code>valid</code> 属性，这个属性只有在<em>它包含的每个控件</em>都有效时才是真。</p><p translation-origin="off">The <code><a href="api/forms/NgForm" class="code-anchor">NgForm</a></code> directive supplements the <code>form</code> element with additional features. It holds the controls you created for the elements with an <code><a href="api/forms/NgModel" class="code-anchor">ngModel</a></code> directive and <code>name</code> attribute, and monitors their properties, including their validity. It also has its own <code>valid</code> property which is true only <em>if every contained control</em> is valid.</p></div><p translation-result="on">如果现在运行这个应用，开始在<em>姓名</em>输入框中键入，添加和删除字符，将看到它们从插值结果中显示和消失。 某一瞬间，它可能是这样的：</p><p translation-origin="off">If you ran the app now and started typing in the <em>Name</em> input box, adding and deleting characters, you'd see them appear and disappear from the interpolated text. At some point it might look like this:</p><figure><img src="generated/images/guide/forms/ng-model-in-action.png" alt="ngModel in action" width="500" height="74"></figure><p translation-result="on">诊断信息可以证明，数据确实从输入框流动到模型，再反向流动回来。</p><p translation-origin="off">The diagnostic is evidence that values really are flowing from the input box to the model and back again.</p><div class="alert is-helpful"><p translation-result="on"><strong>这就是双向数据绑定！</strong>要了解更多信息，参见<a href="guide/template-syntax">模板语法</a>页的<a href="guide/template-syntax#ngModel">使用 NgModel 进行双向绑定</a>。</p><p translation-origin="off">That's <em>two-way data binding</em>. For more information, see <a href="guide/template-syntax#ngModel">Two-way binding with NgModel</a> on the the <a href="guide/template-syntax">Template Syntax</a> page.</p></div><p translation-result="on">注意，<code>&lt;input&gt;</code> 标签还添加了 <code>name</code> 属性 (attribute)，并设置为 "name"，表示英雄的名字。 使用任何唯一的值都可以，但使用具有描述性的名字会更有帮助。 当在表单中使用 <code>[(<a href="api/forms/NgModel" class="code-anchor">ngModel</a>)]</code> 时，必须要定义 <code>name</code> 属性。</p><p translation-origin="off">Notice that you also added a <code>name</code> attribute to the <code>&lt;input&gt;</code> tag and set it to "name", which makes sense for the hero's name. Any unique value will do, but using a descriptive name is helpful. Defining a <code>name</code> attribute is a requirement when using <code>[(<a href="api/forms/NgModel" class="code-anchor">ngModel</a>)]</code> in combination with a form.</p><div class="alert is-helpful"><p translation-result="on">在内部，Angular 创建了一些 <code><a href="api/forms/FormControl" class="code-anchor">FormControl</a></code>，并把它们注册到 Angular 附加到 <code>&lt;form&gt;</code> 标签上的 <code><a href="api/forms/NgForm" class="code-anchor">NgForm</a></code> 指令。 注册每个 <code><a href="api/forms/FormControl" class="code-anchor">FormControl</a></code> 时，使用 <code>name</code> 属性值作为键值。欲知详情，参见前面的 <a href="guide/forms#ngForm">NgForm 指令</a>。</p><p translation-origin="off">Internally, Angular creates <code><a href="api/forms/FormControl" class="code-anchor">FormControl</a></code> instances and registers them with an <code><a href="api/forms/NgForm" class="code-anchor">NgForm</a></code> directive that Angular attached to the <code>&lt;form&gt;</code> tag. Each <code><a href="api/forms/FormControl" class="code-anchor">FormControl</a></code> is registered under the name you assigned to the <code>name</code> attribute. Read more in the previous section, <a href="guide/forms#ngForm">The NgForm directive</a>.</p></div><p translation-result="on">为<em>第二人格</em>和<em>超能力</em>属性添加类似的 <code>[(<a href="api/forms/NgModel" class="code-anchor">ngModel</a>)]</code> 绑定和 <code>name</code> 属性。 抛弃输入框的绑定消息，在组件顶部添加到 <code>diagnostic</code> 属性的新绑定。 这样就能确认双向数据绑定<em>在整个 Hero 模型上</em>都能正常工作了。</p><p translation-origin="off">Add similar <code>[(<a href="api/forms/NgModel" class="code-anchor">ngModel</a>)]</code> bindings and <code>name</code> attributes to <em>Alter Ego</em> and <em>Hero Power</em>. You'll ditch the input box binding message and add a new binding (at the top) to the component's <code>diagnostic</code> property. Then you can confirm that two-way data binding works <em>for the entire hero model</em>.</p><p translation-result="on">修改之后，这个表单的核心是这样的：</p><p translation-origin="off">After revision, the core of the form should look like this:</p><code-example path="forms/src/app/hero-form/hero-form.component.html" linenums="false" header="src/app/hero-form/hero-form.component.html (excerpt)" region="ngModel-2" ng-version="7.0.0"><div style="display:none">{{diagnostic}} &lt;div class="form-group"&gt; &lt;label for="name"&gt;Name&lt;/label&gt; &lt;input type="text" class="form-control" id="name" required [(<a href="api/forms/NgModel" class="code-anchor">ngModel</a>)]="model.name" name="name"&gt; &lt;/div&gt; &lt;div class="form-group"&gt; &lt;label for="alterEgo"&gt;Alter Ego&lt;/label&gt; &lt;input type="text" class="form-control" id="alterEgo" [(<a href="api/forms/NgModel" class="code-anchor">ngModel</a>)]="model.alterEgo" name="alterEgo"&gt; &lt;/div&gt; &lt;div class="form-group"&gt; &lt;label for="power"&gt;Hero Power&lt;/label&gt; &lt;select class="form-control" id="power" required [(<a href="api/forms/NgModel" class="code-anchor">ngModel</a>)]="model.power" name="power"&gt; &lt;<a href="api/forms/NgSelectOption" class="code-anchor">option</a> *<a href="api/common/NgForOf" class="code-anchor">ngFor</a>="let pow of powers" [value]="pow"&gt;{{pow}}&lt;/<a href="api/forms/NgSelectOption" class="code-anchor">option</a>&gt; &lt;/select&gt; &lt;/div&gt;</div><header class="ng-star-inserted">src/app/hero-form/hero-form.component.html (excerpt)</header><aio-code class="headed-code"><pre class="prettyprint lang-">      <button class="material-icons copy-button no-print ng-star-inserted" title="Copy code snippet" aria-label="Copy code snippet from src/app/hero-form/hero-form.component.html (excerpt)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pun">{{</span><span class="pln">diagnostic</span><span class="pun">}}</span><span class="pln">
</span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"form-group"</span><span class="pun">&gt;</span><span class="pln">
  </span><span class="pun">&lt;</span><span class="pln">label </span><span class="kwd">for</span><span class="pun">=</span><span class="str">"name"</span><span class="pun">&gt;</span><span class="typ">Name</span><span class="pun">&lt;/</span><span class="pln">label</span><span class="pun">&gt;</span><span class="pln">
  </span><span class="pun">&lt;</span><span class="pln">input type</span><span class="pun">=</span><span class="str">"text"</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"form-control"</span><span class="pln"> id</span><span class="pun">=</span><span class="str">"name"</span><span class="pln">
         required
         </span><span class="pun">[(</span><a href="api/forms/NgModel" class="code-anchor"><span class="pln">ngModel</span></a><span class="pun">)]=</span><span class="str">"model.name"</span><span class="pln"> name</span><span class="pun">=</span><span class="str">"name"</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">

</span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"form-group"</span><span class="pun">&gt;</span><span class="pln">
  </span><span class="pun">&lt;</span><span class="pln">label </span><span class="kwd">for</span><span class="pun">=</span><span class="str">"alterEgo"</span><span class="pun">&gt;</span><span class="typ">Alter</span><span class="pln"> </span><span class="typ">Ego</span><span class="pun">&lt;/</span><span class="pln">label</span><span class="pun">&gt;</span><span class="pln">
  </span><span class="pun">&lt;</span><span class="pln">input type</span><span class="pun">=</span><span class="str">"text"</span><span class="pln">  </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"form-control"</span><span class="pln"> id</span><span class="pun">=</span><span class="str">"alterEgo"</span><span class="pln">
         </span><span class="pun">[(</span><a href="api/forms/NgModel" class="code-anchor"><span class="pln">ngModel</span></a><span class="pun">)]=</span><span class="str">"model.alterEgo"</span><span class="pln"> name</span><span class="pun">=</span><span class="str">"alterEgo"</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">

</span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"form-group"</span><span class="pun">&gt;</span><span class="pln">
  </span><span class="pun">&lt;</span><span class="pln">label </span><span class="kwd">for</span><span class="pun">=</span><span class="str">"power"</span><span class="pun">&gt;</span><span class="typ">Hero</span><span class="pln"> </span><span class="typ">Power</span><span class="pun">&lt;/</span><span class="pln">label</span><span class="pun">&gt;</span><span class="pln">
  </span><span class="pun">&lt;</span><span class="kwd">select</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"form-control"</span><span class="pln">  id</span><span class="pun">=</span><span class="str">"power"</span><span class="pln">
          required
          </span><span class="pun">[(</span><a href="api/forms/NgModel" class="code-anchor"><span class="pln">ngModel</span></a><span class="pun">)]=</span><span class="str">"model.power"</span><span class="pln"> name</span><span class="pun">=</span><span class="str">"power"</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="pun">&lt;</span><a href="api/forms/NgSelectOption" class="code-anchor"><span class="pln">option</span></a><span class="pln"> </span><span class="pun">*</span><a href="api/common/NgForOf" class="code-anchor"><span class="pln">ngFor</span></a><span class="pun">=</span><span class="str">"let pow of powers"</span><span class="pln"> </span><span class="pun">[</span><span class="kwd">value</span><span class="pun">]=</span><span class="str">"pow"</span><span class="pun">&gt;{{</span><span class="pln">pow</span><span class="pun">}}&lt;/</span><a href="api/forms/NgSelectOption" class="code-anchor"><span class="pln">option</span></a><span class="pun">&gt;</span><span class="pln">
  </span><span class="pun">&lt;/</span><span class="kwd">select</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span></code>
    </pre></aio-code></code-example><div class="alert is-helpful"><ul><li><p translation-result="on">每个 input 元素都有 <code>id</code> 属性，<code>label</code> 元素的 <code>for</code> 属性用它来匹配到对应的输入控件。</p><p translation-origin="off">Each input element has an <code>id</code> property that is used by the <code>label</code> element's <code>for</code> attribute to match the label to its input control.</p></li><li><p translation-result="on">每个 input 元素都有 <code>name</code> 属性，Angular 表单用它注册控件。</p><p translation-origin="off">Each input element has a <code>name</code> property that is required by Angular forms to register the control with the form.</p></li></ul></div><p translation-result="on">如果现在运行本应用，修改 Hero 模型的每个属性，表单是这样的：</p><p translation-origin="off">If you run the app now and change every hero model property, the form might display like this:</p><figure><img src="generated/images/guide/forms/ng-model-in-action-2.png" alt="ngModel in action" width="515" height="377"></figure><p translation-result="on">表单顶部的诊断信息反映出所做的一切更改。</p><p translation-origin="off">The diagnostic near the top of the form confirms that all of your changes are reflected in the model.</p><p translation-result="on">表单顶部的 <code>{{diagnostic}}</code> 绑定已经完成了它的使命，<strong>删除</strong>它。</p><p translation-origin="off"><em>Delete</em> the <code>{{diagnostic}}</code> binding at the top as it has served its purpose.</p><h2 id="track-control-state-and-validity-with-ngmodel" translation-result="on">通过 <strong>ngModel</strong> 跟踪修改状态与有效性验证<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#track-control-state-and-validity-with-ngmodel"><i class="material-icons">link</i></a></h2><h2 translation-origin="off" id="track-control-state-and-validity-with-ngmodel">Track control state and validity with <em>ngModel</em><a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#track-control-state-and-validity-with-ngmodel"><i class="material-icons">link</i></a></h2><p translation-result="on">在表单中使用 <code><a href="api/forms/NgModel" class="code-anchor">ngModel</a></code> 可以获得比仅使用双向数据绑定更多的控制权。它还会告诉你很多信息：用户碰过此控件吗？它的值变化了吗？数据变得无效了吗？</p><p translation-origin="off">Using <code><a href="api/forms/NgModel" class="code-anchor">ngModel</a></code> in a form gives you more than just two-way data binding. It also tells you if the user touched the control, if the value changed, or if the value became invalid.</p><p translation-result="on"><em>NgModel</em> 指令不仅仅跟踪状态。它还使用特定的 Angular CSS 类来更新控件，以反映当前状态。 可以利用这些 CSS 类来修改控件的外观，显示或隐藏消息。</p><p translation-origin="off">The <em>NgModel</em> directive doesn't just track state; it updates the control with special Angular CSS classes that reflect the state. You can leverage those class names to change the appearance of the control.</p><table><tbody><tr><th><p translation-result="on">状态</p><p translation-origin="off">State</p></th><th><p translation-result="on">为真时的 CSS 类</p><p translation-origin="off">Class if true</p></th><th><p translation-result="on">为假时的 CSS 类</p><p translation-origin="off">Class if false</p></th></tr><tr><td><p translation-result="on">控件被访问过。</p><p translation-origin="off">The control has been visited.</p></td><td><p> <code>ng-touched</code></p></td><td><p> <code>ng-untouched</code></p></td></tr><tr><td><p translation-result="on">控件的值变化了。</p><p translation-origin="off">The control's value has changed.</p></td><td><p> <code>ng-dirty</code></p></td><td><p> <code>ng-pristine</code></p></td></tr><tr><td><p translation-result="on">控件的值有效。</p><p translation-origin="off">The control's value is valid.</p></td><td><p> <code>ng-valid</code></p></td><td><p> <code>ng-invalid</code></p></td></tr></tbody></table><p translation-result="on">往姓名 <code>&lt;input&gt;</code> 标签上添加名叫 <strong>spy</strong> 的临时<a href="guide/template-syntax#ref-vars">模板引用变量</a>， 然后用这个 spy 来显示它上面的所有 CSS 类。</p><p translation-origin="off">Temporarily add a <a href="guide/template-syntax#ref-vars">template reference variable</a> named <code>spy</code> to the <em>Name</em> <code>&lt;input&gt;</code> tag and use it to display the input's CSS classes.</p><code-example path="forms/src/app/hero-form/hero-form.component.html" linenums="false" header="src/app/hero-form/hero-form.component.html (excerpt)" region="ngModelName-2" ng-version="7.0.0"><div style="display:none">&lt;input type="text" class="form-control" id="name" required [(<a href="api/forms/NgModel" class="code-anchor">ngModel</a>)]="model.name" name="name" #spy&gt; &lt;br&gt;TODO: remove this: {{spy.className}}</div><header class="ng-star-inserted">src/app/hero-form/hero-form.component.html (excerpt)</header><aio-code class="headed-code"><pre class="prettyprint lang-">      <button class="material-icons copy-button no-print ng-star-inserted" title="Copy code snippet" aria-label="Copy code snippet from src/app/hero-form/hero-form.component.html (excerpt)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"text"</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"form-control"</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"name"</span><span class="pln">
  </span><span class="atn">required</span><span class="pln">
  [(</span><a href="api/forms/NgModel" class="code-anchor"><span class="atn">ngModel</span></a><span class="pln">)]</span><span class="pun">=</span><span class="atv">"model.name"</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"name"</span><span class="pln">
  #</span><span class="atn">spy</span><span class="tag">&gt;</span><span class="pln">
</span><span class="tag">&lt;br&gt;</span><span class="pln">TODO: remove this: {{spy.className}}</span></code>
    </pre></aio-code></code-example><p translation-result="on">现在，运行本应用，并让<em>姓名</em>输入框获得焦点。 然后严格按照下面四个步骤来做：</p><p translation-origin="off">Now run the app and look at the <em>Name</em> input box. Follow these steps <em>precisely</em>:</p><ol><li><p translation-result="on">查看输入框，但别碰它。</p><p translation-origin="off">Look but don't touch.</p></li><li><p translation-result="on">点击输入框，然后点击输入框外面。</p><p translation-origin="off">Click inside the name box, then click outside it.</p></li><li><p translation-result="on">在名字的末尾添加些斜杠。</p><p translation-origin="off">Add slashes to the end of the name.</p></li><li><p translation-result="on">删除名字。</p><p translation-origin="off">Erase the name.</p></li></ol><p translation-result="on">动作和它对应的效果如下：</p><p translation-origin="off">The actions and effects are as follows:</p><figure><img src="generated/images/guide/forms/control-state-transitions-anim.gif" alt="Control State Transition" width="540" height="72"></figure><p translation-result="on">你会看到下列转换及其类名：</p><p translation-origin="off">You should see the following transitions and class names:</p><figure><img src="generated/images/guide/forms/ng-control-class-changes.png" alt="Control state transitions" width="600" height="311"></figure><p translation-result="on">(<code>ng-valid</code> | <code>ng-invalid</code>)这一对是最有趣的部分，因为当数据变得无效时，你希望发出强力的视觉信号， 还想要标记出必填字段。可以通过加入自定义 CSS 来提供视觉反馈。</p><p translation-origin="off">The <code>ng-valid</code>/<code>ng-invalid</code> pair is the most interesting, because you want to send a strong visual signal when the values are invalid. You also want to mark required fields. To create such visual feedback, add definitions for the <code>ng-*</code> CSS classes.</p><p translation-result="on"><strong>删除</strong>模板引用变量 <code>#spy</code> 和 <code>TODO</code>，因为它们已经完成了使命。</p><p translation-origin="off"><em>Delete</em> the <code>#spy</code> template reference variable and the <code>TODO</code> as they have served their purpose.</p><h2 id="add-custom-css-for-visual-feedback" translation-result="on">添加用于视觉反馈的自定义 CSS<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#add-custom-css-for-visual-feedback"><i class="material-icons">link</i></a></h2><h2 translation-origin="off" id="add-custom-css-for-visual-feedback">Add custom CSS for visual feedback<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#add-custom-css-for-visual-feedback"><i class="material-icons">link</i></a></h2><p translation-result="on">可以在输入框的左侧添加带颜色的竖条，用于标记必填字段和无效输入：</p><p translation-origin="off">You can mark required fields and invalid data at the same time with a colored bar on the left of the input box:</p><figure><img src="generated/images/guide/forms/validity-required-indicator.png" alt="Invalid Form" width="600" height="171"></figure><p translation-result="on">在新建的 <code>forms.css</code> 文件中，添加两个样式来实现这一效果。把这个文件添加到项目中，与 <code>index.html</code> 相邻。</p><p translation-origin="off">You achieve this effect by adding these class definitions to a new <code>forms.css</code> file that you add to the project as a sibling to <code>index.html</code>:</p><code-example path="forms/src/assets/forms.css" header="src/assets/forms.css" ng-version="7.0.0"><div style="display:none">.ng-valid[required], .ng-valid.required { border-left: 5px solid #42A948; /* green */ } .ng-invalid:not(form) { border-left: 5px solid #a94442; /* red */ }</div><header class="ng-star-inserted">src/assets/forms.css</header><aio-code class="headed-code"><pre class="prettyprint lang-">      <button class="material-icons copy-button no-print ng-star-inserted" title="Copy code snippet" aria-label="Copy code snippet from src/assets/forms.css">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pun">.</span><span class="pln">ng</span><span class="pun">-</span><span class="pln">valid</span><span class="pun">[</span><span class="pln">required</span><span class="pun">],</span><span class="pln"> </span><span class="pun">.</span><span class="pln">ng</span><span class="pun">-</span><span class="pln">valid</span><span class="pun">.</span><span class="pln">required  </span><span class="pun">{</span><span class="pln">
  border</span><span class="pun">-</span><span class="pln">left</span><span class="pun">:</span><span class="pln"> </span><span class="lit">5px</span><span class="pln"> solid </span><span class="com">#42A948; /* green */</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="pun">.</span><span class="pln">ng</span><span class="pun">-</span><span class="pln">invalid</span><span class="pun">:</span><span class="kwd">not</span><span class="pun">(</span><span class="pln">form</span><span class="pun">)</span><span class="pln">  </span><span class="pun">{</span><span class="pln">
  border</span><span class="pun">-</span><span class="pln">left</span><span class="pun">:</span><span class="pln"> </span><span class="lit">5px</span><span class="pln"> solid </span><span class="com">#a94442; /* red */</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">修改 <code>index.html</code> 中的 <code>&lt;head&gt;</code>，以包含这个样式表：</p><p translation-origin="off">Update the <code>&lt;head&gt;</code> of <code>index.html</code> to include this style sheet:</p><code-example path="forms/src/index.html" linenums="false" header="src/index.html (styles)" region="styles" ng-version="7.0.0"><div style="display:none">&lt;link rel="stylesheet" <a href="api/router/RouterLinkWithHref#href" class="code-anchor">href</a>="assets/forms.css"&gt;</div><header class="ng-star-inserted">src/index.html (styles)</header><aio-code class="headed-code"><pre class="prettyprint lang-">      <button class="material-icons copy-button no-print ng-star-inserted" title="Copy code snippet" aria-label="Copy code snippet from src/index.html (styles)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;link</span><span class="pln"> </span><span class="atn">rel</span><span class="pun">=</span><span class="atv">"stylesheet"</span><span class="pln"> </span><a href="api/router/RouterLinkWithHref#href" class="code-anchor"><span class="atn">href</span></a><span class="pun">=</span><span class="atv">"assets/forms.css"</span><span class="tag">&gt;</span></code>
    </pre></aio-code></code-example><h2 id="show-and-hide-validation-error-messages" translation-result="on">显示和隐藏验证错误信息<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#show-and-hide-validation-error-messages"><i class="material-icons">link</i></a></h2><h2 translation-origin="off" id="show-and-hide-validation-error-messages">Show and hide validation error messages<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#show-and-hide-validation-error-messages"><i class="material-icons">link</i></a></h2><p translation-result="on">你还能做的更好。“Name” 输入框是必填的，清空它会让左侧的条变红。这表示<em>某些东西</em>是错的，但用户不知道错在哪里，或者如何纠正。 可以借助 <code>ng-invalid</code> 类来给出有用的提示。</p><p translation-origin="off">You can improve the form. The <em>Name</em> input box is required and clearing it turns the bar red. That says something is wrong but the user doesn't know <em>what</em> is wrong or what to do about it. Leverage the control's state to reveal a helpful message.</p><p translation-result="on">当用户删除姓名时，应该是这样的：</p><p translation-origin="off">When the user deletes the name, the form should look like this:</p><figure><img src="generated/images/guide/forms/name-required-error.png" alt="Name required" width="400" height="108"></figure><p translation-result="on">要达到这个效果，在 <code>&lt;input&gt;</code> 标签中添加：</p><p translation-origin="off">To achieve this effect, extend the <code>&lt;input&gt;</code> tag with the following:</p><ul><li><p translation-result="on"><a href="guide/template-syntax#ref-vars">模板引用变量</a></p><p translation-origin="off">A <a href="guide/template-syntax#ref-vars">template reference variable</a>.</p></li><li><p translation-result="on">“is required”消息，放在邻近的 <code>&lt;div&gt;</code> 元素中，只有当控件无效时，才显示它。</p><p translation-origin="off">The "<em>is required</em>" message in a nearby <code>&lt;div&gt;</code>, which you'll display only if the control is invalid.</p></li></ul><p translation-result="on">下面这个例子中把一条错误信息添加到了<code>name</code>输入框中：</p><p translation-origin="off">Here's an example of an error message added to the <em>name</em> input box:</p><code-example path="forms/src/app/hero-form/hero-form.component.html" linenums="false" header="src/app/hero-form/hero-form.component.html (excerpt)" region="name-with-error-msg" ng-version="7.0.0"><div style="display:none">&lt;label for="name"&gt;Name&lt;/label&gt; &lt;input type="text" class="form-control" id="name" required [(<a href="api/forms/NgModel" class="code-anchor">ngModel</a>)]="model.name" name="name" #name="<a href="api/forms/NgModel" class="code-anchor">ngModel</a>"&gt; &lt;div [hidden]="name.valid || name.pristine" class="alert alert-danger"&gt; Name is required &lt;/div&gt;</div><header class="ng-star-inserted">src/app/hero-form/hero-form.component.html (excerpt)</header><aio-code class="headed-code"><pre class="prettyprint lang-">      <button class="material-icons copy-button no-print ng-star-inserted" title="Copy code snippet" aria-label="Copy code snippet from src/app/hero-form/hero-form.component.html (excerpt)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;label</span><span class="pln"> </span><span class="atn">for</span><span class="pun">=</span><span class="atv">"name"</span><span class="tag">&gt;</span><span class="pln">Name</span><span class="tag">&lt;/label&gt;</span><span class="pln">
</span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"text"</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"form-control"</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"name"</span><span class="pln">
       </span><span class="atn">required</span><span class="pln">
       [(</span><a href="api/forms/NgModel" class="code-anchor"><span class="atn">ngModel</span></a><span class="pln">)]</span><span class="pun">=</span><span class="atv">"model.name"</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"name"</span><span class="pln">
       #</span><span class="atn">name</span><span class="pun">=</span><span class="atv">"</span><a href="api/forms/NgModel" class="code-anchor"><span class="atv">ngModel</span></a><span class="atv">"</span><span class="tag">&gt;</span><span class="pln">
</span><span class="tag">&lt;div</span><span class="pln"> [</span><span class="atn">hidden</span><span class="pln">]</span><span class="pun">=</span><span class="atv">"name.valid || name.pristine"</span><span class="pln">
     </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"alert alert-danger"</span><span class="tag">&gt;</span><span class="pln">
  Name is required
</span><span class="tag">&lt;/div&gt;</span></code>
    </pre></aio-code></code-example><p translation-result="on">模板引用变量可以访问模板中输入框的 Angular 控件。 这里，创建了名叫 <code>name</code> 的变量，并且赋值为 "ngModel"。</p><p translation-origin="off">You need a template reference variable to access the input box's Angular control from within the template. Here you created a variable called <code>name</code> and gave it the value "ngModel".</p><div class="alert is-helpful"><p translation-result="on">为什么是 “ngModel”？ 指令的 <a href="api/core/Directive">exportAs</a> 属性告诉 Angular 如何链接模板引用变量到指令。 这里把 <code>name</code> 设置为 <code><a href="api/forms/NgModel" class="code-anchor">ngModel</a></code> 是因为 <code><a href="api/forms/NgModel" class="code-anchor">ngModel</a></code> 指令的 <code><a href="api/core/Directive#exportAs" class="code-anchor">exportAs</a></code> 属性设置成了 “ngModel”。</p><p translation-origin="off">Why "ngModel"? A directive's <a href="api/core/Directive">exportAs</a> property tells Angular how to link the reference variable to the directive. You set <code>name</code> to <code><a href="api/forms/NgModel" class="code-anchor">ngModel</a></code> because the <code><a href="api/forms/NgModel" class="code-anchor">ngModel</a></code> directive's <code><a href="api/core/Directive#exportAs" class="code-anchor">exportAs</a></code> property happens to be "ngModel".</p></div><p translation-result="on">你把 <code>div</code> 元素的 <code>hidden</code> 属性绑定到 <code>name</code> 控件的属性，这样就可以控制“姓名”字段错误信息的可见性了。</p><p translation-origin="off">You control visibility of the name error message by binding properties of the <code>name</code> control to the message <code>&lt;div&gt;</code> element's <code>hidden</code> property.</p><code-example path="forms/src/app/hero-form/hero-form.component.html" linenums="false" header="src/app/hero-form/hero-form.component.html (hidden-error-msg)" region="hidden-error-msg" ng-version="7.0.0"><div style="display:none">&lt;div [hidden]="name.valid || name.pristine" class="alert alert-danger"&gt;</div><header class="ng-star-inserted">src/app/hero-form/hero-form.component.html (hidden-error-msg)</header><aio-code class="headed-code"><pre class="prettyprint lang-">      <button class="material-icons copy-button no-print ng-star-inserted" title="Copy code snippet" aria-label="Copy code snippet from src/app/hero-form/hero-form.component.html (hidden-error-msg)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;div</span><span class="pln"> [</span><span class="atn">hidden</span><span class="pln">]</span><span class="pun">=</span><span class="atv">"name.valid || name.pristine"</span><span class="pln">
     </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"alert alert-danger"</span><span class="tag">&gt;</span></code>
    </pre></aio-code></code-example><p translation-result="on">上例中，当控件是有效的 (valid) 或全新的 (pristine) 时，隐藏消息。 “全新的”意味着从它显示在表单中开始，用户还从未修改过它的值。</p><p translation-origin="off">In this example, you hide the message when the control is valid or pristine; "pristine" means the user hasn't changed the value since it was displayed in this form.</p><p translation-result="on">这种用户体验取决于开发人员的选择。有些人会希望任何时候都显示这条消息。 如果忽略了 <code>pristine</code> 状态，就会只在值有效时隐藏此消息。 如果往这个组件中传入全新（空）的英雄，或者无效的英雄，将立刻看到错误信息 —— 虽然你还啥都没做。</p><p translation-origin="off">This user experience is the developer's choice. Some developers want the message to display at all times. If you ignore the <code>pristine</code> state, you would hide the message only when the value is valid. If you arrive in this component with a new (blank) hero or an invalid hero, you'll see the error message immediately, before you've done anything.</p><p translation-result="on">有些人会为这种行为感到不安。它们希望只有在用户做出无效的更改时才显示这个消息。 如果当控件是“全新”状态时也隐藏消息，就能达到这个目的。 在往表单中添加新英雄时，将看到这种选择的重要性。</p><p translation-origin="off">Some developers want the message to display only when the user makes an invalid change. Hiding the message while the control is "pristine" achieves that goal. You'll see the significance of this choice when you add a new hero to the form.</p><p translation-result="on">英雄的<em>第二人格</em>是可选项，所以不用改它。</p><p translation-origin="off">The hero <em>Alter Ego</em> is optional so you can leave that be.</p><p translation-result="on">英雄的<em>超能力</em>选项是必填的。 只要愿意，可以往 <code>&lt;select&gt;</code> 上添加相同的错误处理。 但没有必要，这个选择框已经限制了“超能力”只能选有效值。</p><p translation-origin="off">Hero <em>Power</em> selection is required. You can add the same kind of error handling to the <code>&lt;select&gt;</code> if you want, but it's not imperative because the selection box already constrains the power to valid values.</p><p translation-result="on">现在，你要在这个表单中添加新的英雄。 在表单的底部放置“New Hero（新增英雄）”按钮，并把它的点击事件绑定到组件上的 <code>newHero</code> 方法。</p><p translation-origin="off">Now you'll add a new hero in this form. Place a <em>New Hero</em> button at the bottom of the form and bind its click event to a <code>newHero</code> component method.</p><code-example path="forms/src/app/hero-form/hero-form.component.html" region="new-hero-button-no-reset" header="src/app/hero-form/hero-form.component.html (New Hero button)" ng-version="7.0.0"><div style="display:none">&lt;button type="button" class="btn btn-default" (click)="newHero()"&gt;New Hero&lt;/button&gt;</div><header class="ng-star-inserted">src/app/hero-form/hero-form.component.html (New Hero button)</header><aio-code class="headed-code"><pre class="prettyprint lang-">      <button class="material-icons copy-button no-print ng-star-inserted" title="Copy code snippet" aria-label="Copy code snippet from src/app/hero-form/hero-form.component.html (New Hero button)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;button</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"button"</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"btn btn-default"</span><span class="pln"> (</span><span class="atn">click</span><span class="pln">)</span><span class="pun">=</span><span class="atv">"newHero()"</span><span class="tag">&gt;</span><span class="pln">New Hero</span><span class="tag">&lt;/button&gt;</span></code>
    </pre></aio-code></code-example><code-example path="forms/src/app/hero-form/hero-form.component.ts" region="new-hero" header="src/app/hero-form/hero-form.component.ts (New Hero method)" linenums="false" ng-version="7.0.0"><div style="display:none">newHero() { this.model = new Hero(42, '', ''); }</div><header class="ng-star-inserted">src/app/hero-form/hero-form.component.ts (New Hero method)</header><aio-code class="headed-code"><pre class="prettyprint lang-">      <button class="material-icons copy-button no-print ng-star-inserted" title="Copy code snippet" aria-label="Copy code snippet from src/app/hero-form/hero-form.component.ts (New Hero method)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">newHero</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">model </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Hero</span><span class="pun">(</span><span class="lit">42</span><span class="pun">,</span><span class="pln"> </span><span class="str">''</span><span class="pun">,</span><span class="pln"> </span><span class="str">''</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">再次运行应用，点击 <em>New Hero</em> 按钮，表单被清空了。 输入框左侧的<em>必填项</em>竖条是红色的，表示 <code>name</code> 和 <code>power</code> 属性是无效的。 这可以理解，因为有一些必填字段。 错误信息是隐藏的，因为表单还是全新的，还没有修改任何东西。</p><p translation-origin="off">Run the application again, click the <em>New Hero</em> button, and the form clears. The <em>required</em> bars to the left of the input box are red, indicating invalid <code>name</code> and <code>power</code> properties. That's understandable as these are required fields. The error messages are hidden because the form is pristine; you haven't changed anything yet.</p><p translation-result="on">输入名字，再次点击 <em>New Hero</em> 按钮。 这次，出现了错误信息！为什么？你不希望显示新（空）的英雄时，出现错误信息。</p><p translation-origin="off">Enter a name and click <em>New Hero</em> again. The app displays a <em>Name is required</em> error message. You don't want error messages when you create a new (empty) hero. Why are you getting one now?</p><p translation-result="on">使用浏览器工具审查这个元素就会发现，这个 <em>name</em> 输入框并不是全新的。 表单记得你在点击 <em>New Hero</em> 前输入的名字。 更换了英雄对象<em>并不会重置控件的“全新”状态</em>。</p><p translation-origin="off">Inspecting the element in the browser tools reveals that the <em>name</em> input box is <em>no longer pristine</em>. The form remembers that you entered a name before clicking <em>New Hero</em>. Replacing the hero object <em>did not restore the pristine state</em> of the form controls.</p><p translation-result="on">你必须清除所有标记，在调用 <code>newHero()</code> 方法后调用表单的 <code>reset()</code> 方法即可。</p><p translation-origin="off">You have to clear all of the flags imperatively, which you can do by calling the form's <code>reset()</code> method after calling the <code>newHero()</code> method.</p><code-example path="forms/src/app/hero-form/hero-form.component.html" region="new-hero-button-form-reset" header="src/app/hero-form/hero-form.component.html (Reset the form)" ng-version="7.0.0"><div style="display:none">&lt;button type="button" class="btn btn-default" (click)="newHero(); heroForm.reset()"&gt;New Hero&lt;/button&gt;</div><header class="ng-star-inserted">src/app/hero-form/hero-form.component.html (Reset the form)</header><aio-code class="headed-code"><pre class="prettyprint lang-">      <button class="material-icons copy-button no-print ng-star-inserted" title="Copy code snippet" aria-label="Copy code snippet from src/app/hero-form/hero-form.component.html (Reset the form)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;button</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"button"</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"btn btn-default"</span><span class="pln"> (</span><span class="atn">click</span><span class="pln">)</span><span class="pun">=</span><span class="atv">"newHero(); heroForm.reset()"</span><span class="tag">&gt;</span><span class="pln">New Hero</span><span class="tag">&lt;/button&gt;</span></code>
    </pre></aio-code></code-example><p translation-result="on">现在点击“New Hero”重设表单和它的控制标记。</p><p translation-origin="off">Now clicking "New Hero" resets both the form and its control flags.</p><h2 id="submit-the-form-with-ngsubmit" translation-result="on">使用 <em>ngSubmit</em> 提交该表单<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#submit-the-form-with-ngsubmit"><i class="material-icons">link</i></a></h2><h2 translation-origin="off" id="submit-the-form-with-ngsubmit">Submit the form with <em>ngSubmit</em><a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#submit-the-form-with-ngsubmit"><i class="material-icons">link</i></a></h2><p translation-result="on">在填表完成之后，用户还应该能提交这个表单。 “Submit（提交）”按钮位于表单的底部，它自己不做任何事，但因为有特殊的 type 值 (<code>type="submit"</code>)，所以会触发表单提交。</p><p translation-origin="off">The user should be able to submit this form after filling it in. The <em>Submit</em> button at the bottom of the form does nothing on its own, but it will trigger a form submit because of its type (<code>type="submit"</code>).</p><p translation-result="on">现在这样仅仅触发“表单提交”是没用的。 要让它有用，就要把该表单的 <code>ngSubmit</code> 事件属性绑定到英雄表单组件的 <code>onSubmit()</code> 方法上：</p><p translation-origin="off">A "form submit" is useless at the moment. To make it useful, bind the form's <code>ngSubmit</code> event property to the hero form component's <code>onSubmit()</code> method:</p><code-example path="forms/src/app/hero-form/hero-form.component.html" linenums="false" header="src/app/hero-form/hero-form.component.html (ngSubmit)" region="ngSubmit" ng-version="7.0.0"><div style="display:none">&lt;form (ngSubmit)="onSubmit()" #heroForm="<a href="api/forms/NgForm" class="code-anchor">ngForm</a>"&gt;</div><header class="ng-star-inserted">src/app/hero-form/hero-form.component.html (ngSubmit)</header><aio-code class="headed-code"><pre class="prettyprint lang-">      <button class="material-icons copy-button no-print ng-star-inserted" title="Copy code snippet" aria-label="Copy code snippet from src/app/hero-form/hero-form.component.html (ngSubmit)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;form</span><span class="pln"> (</span><span class="atn">ngSubmit</span><span class="pln">)</span><span class="pun">=</span><span class="atv">"onSubmit()"</span><span class="pln"> #</span><span class="atn">heroForm</span><span class="pun">=</span><span class="atv">"</span><a href="api/forms/NgForm" class="code-anchor"><span class="atv">ngForm</span></a><span class="atv">"</span><span class="tag">&gt;</span></code>
    </pre></aio-code></code-example><p translation-result="on">你已经定义了一个模板引用变量 <code>#heroForm</code>，并且把赋值为“ngForm”。 现在，就可以在“Submit”按钮中访问这个表单了。</p><p translation-origin="off">You'd already defined a template reference variable, <code>#heroForm</code>, and initialized it with the value "ngForm". Now, use that variable to access the form with the Submit button.</p><p translation-result="on">你要把表单的总体有效性通过 <code>heroForm</code> 变量绑定到此按钮的 <code>disabled</code> 属性上，代码如下：</p><p translation-origin="off">You'll bind the form's overall validity via the <code>heroForm</code> variable to the button's <code>disabled</code> property using an event binding. Here's the code:</p><code-example path="forms/src/app/hero-form/hero-form.component.html" linenums="false" header="src/app/hero-form/hero-form.component.html (submit-button)" region="submit-button" ng-version="7.0.0"><div style="display:none">&lt;button type="submit" class="btn btn-success" [disabled]="!heroForm.form.valid"&gt;Submit&lt;/button&gt;</div><header class="ng-star-inserted">src/app/hero-form/hero-form.component.html (submit-button)</header><aio-code class="headed-code"><pre class="prettyprint lang-">      <button class="material-icons copy-button no-print ng-star-inserted" title="Copy code snippet" aria-label="Copy code snippet from src/app/hero-form/hero-form.component.html (submit-button)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;button</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"submit"</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"btn btn-success"</span><span class="pln"> [</span><span class="atn">disabled</span><span class="pln">]</span><span class="pun">=</span><span class="atv">"!heroForm.form.valid"</span><span class="tag">&gt;</span><span class="pln">Submit</span><span class="tag">&lt;/button&gt;</span></code>
    </pre></aio-code></code-example><p translation-result="on">重新运行应用。表单打开时，状态是有效的，按钮是可用的。</p><p translation-origin="off">If you run the application now, you find that the button is enabled—although it doesn't do anything useful yet.</p><p translation-result="on">现在，如果你删除<em>姓名</em>，就会违反“必填姓名”规则，就会像以前那样显示出错误信息。同时，Submit 按钮也被禁用了。</p><p translation-origin="off">Now if you delete the Name, you violate the "required" rule, which is duly noted in the error message. The <em>Submit</em> button is also disabled.</p><p translation-result="on">没感觉吗？再想一会儿。如果没有 Angular <code><a href="api/forms/NgForm" class="code-anchor">NgForm</a></code> 的帮助，又该怎么让按钮的禁用/启用状态和表单的有效性关联起来呢？</p><p translation-origin="off">Not impressed? Think about it for a moment. What would you have to do to wire the button's enable/disabled state to the form's validity without Angular's help?</p><p translation-result="on">对你来说，它就是这么简单：</p><p translation-origin="off">For you, it was as simple as this:</p><ol><li><p translation-result="on">定义模板引用变量，放在（强化过的）form 元素上</p><p translation-origin="off">Define a template reference variable on the (enhanced) form element.</p></li><li><p translation-result="on">从很多行之外的按钮上引用这个变量。</p><p translation-origin="off">Refer to that variable in a button many lines away.</p></li></ol><h2 id="toggle-two-form-regions-extra-credit" translation-result="on">切换两个表单区域（额外的奖励）<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#toggle-two-form-regions-extra-credit"><i class="material-icons">link</i></a></h2><h2 translation-origin="off" id="toggle-two-form-regions-extra-credit">Toggle two form regions (extra credit)<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#toggle-two-form-regions-extra-credit"><i class="material-icons">link</i></a></h2><p translation-result="on">提交表单还是不够激动人心。</p><p translation-origin="off">Submitting the form isn't terribly dramatic at the moment.</p><div class="alert is-helpful"><p translation-result="on">对演示来说，这个收场很平淡的。老实说，即使让它更出彩，也无法教给你任何关于表单的新知识。 但这是练习新学到的绑定技能的好机会。 如果你不感兴趣，可以跳到本章的总结部分。</p><p translation-origin="off">An unsurprising observation for a demo. To be honest, jazzing it up won't teach you anything new about forms. But this is an opportunity to exercise some of your newly won binding skills. If you aren't interested, skip to this page's conclusion.</p></div><p translation-result="on">来实现一些更炫的视觉效果吧。 隐藏掉数据输入框，显示一些别的东西。</p><p translation-origin="off">For a more strikingly visual effect, hide the data entry area and display something else.</p><p translation-result="on">先把表单包裹进 <code>&lt;div&gt;</code> 中，再把它的 <code>hidden</code> 属性绑定到 <code>HeroFormComponent.submitted</code> 属性。</p><p translation-origin="off">Wrap the form in a <code>&lt;div&gt;</code> and bind its <code>hidden</code> property to the <code>HeroFormComponent.submitted</code> property.</p><code-example path="forms/src/app/hero-form/hero-form.component.html" linenums="false" header="src/app/hero-form/hero-form.component.html (excerpt)" region="edit-div" ng-version="7.0.0"><div style="display:none">&lt;div [hidden]="submitted"&gt; &lt;h1&gt;Hero <a href="api/forms/Form" class="code-anchor">Form</a>&lt;/h1&gt; &lt;form (ngSubmit)="onSubmit()" #heroForm="<a href="api/forms/NgForm" class="code-anchor">ngForm</a>"&gt; &lt;!-- ... all of the form ... --&gt; &lt;/form&gt; &lt;/div&gt;</div><header class="ng-star-inserted">src/app/hero-form/hero-form.component.html (excerpt)</header><aio-code class="headed-code"><pre class="prettyprint lang-">      <button class="material-icons copy-button no-print ng-star-inserted" title="Copy code snippet" aria-label="Copy code snippet from src/app/hero-form/hero-form.component.html (excerpt)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;div</span><span class="pln"> [</span><span class="atn">hidden</span><span class="pln">]</span><span class="pun">=</span><span class="atv">"submitted"</span><span class="tag">&gt;</span><span class="pln">
  </span><span class="tag">&lt;h1&gt;</span><span class="pln">Hero </span><a href="api/forms/Form" class="code-anchor"><span class="pln">Form</span></a><span class="tag">&lt;/h1&gt;</span><span class="pln">
  </span><span class="tag">&lt;form</span><span class="pln"> (</span><span class="atn">ngSubmit</span><span class="pln">)</span><span class="pun">=</span><span class="atv">"onSubmit()"</span><span class="pln"> #</span><span class="atn">heroForm</span><span class="pun">=</span><span class="atv">"</span><a href="api/forms/NgForm" class="code-anchor"><span class="atv">ngForm</span></a><span class="atv">"</span><span class="tag">&gt;</span><span class="pln">

     </span><span class="com">&lt;!-- ... all of the form ... --&gt;</span><span class="pln">

  </span><span class="tag">&lt;/form&gt;</span><span class="pln">
</span><span class="tag">&lt;/div&gt;</span></code>
    </pre></aio-code></code-example><p translation-result="on">主表单从一开始就是可见的，因为 <code>submitted</code> 属性是 false，直到提交了这个表单。 来自 <code>HeroFormComponent</code> 的代码片段证实了这一点：</p><p translation-origin="off">The main form is visible from the start because the <code>submitted</code> property is false until you submit the form, as this fragment from the <code>HeroFormComponent</code> shows:</p><code-example path="forms/src/app/hero-form/hero-form.component.ts" linenums="false" header="src/app/hero-form/hero-form.component.ts (submitted)" region="submitted" ng-version="7.0.0"><div style="display:none">submitted = false; onSubmit() { this.submitted = true; }</div><header class="ng-star-inserted">src/app/hero-form/hero-form.component.ts (submitted)</header><aio-code class="headed-code"><pre class="prettyprint lang-">      <button class="material-icons copy-button no-print ng-star-inserted" title="Copy code snippet" aria-label="Copy code snippet from src/app/hero-form/hero-form.component.ts (submitted)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="pln">submitted </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">

onSubmit</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">submitted </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span></code>
    </pre></aio-code></code-example><p translation-result="on">当点击 Submit 按钮时，<code>submitted</code> 标志会变成 true，并且表单像预想中一样消失了。</p><p translation-origin="off">When you click the <em>Submit</em> button, the <code>submitted</code> flag becomes true and the form disappears as planned.</p><p translation-result="on">现在，当表单处于已提交状态时，需要显示一些别的东西。 在刚刚写的 <code>&lt;div&gt;</code> 包装下方，添加下列 HTML 语句：</p><p translation-origin="off">Now the app needs to show something else while the form is in the submitted state. Add the following HTML below the <code>&lt;div&gt;</code> wrapper you just wrote:</p><code-example path="forms/src/app/hero-form/hero-form.component.html" linenums="false" header="src/app/hero-form/hero-form.component.html (excerpt)" region="submitted" ng-version="7.0.0"><div style="display:none">&lt;div [hidden]="!submitted"&gt; &lt;h2&gt;You submitted the following:&lt;/h2&gt; &lt;div class="row"&gt; &lt;div class="col-xs-3"&gt;Name&lt;/div&gt; &lt;div class="col-xs-9"&gt;{{ model.name }}&lt;/div&gt; &lt;/div&gt; &lt;div class="row"&gt; &lt;div class="col-xs-3"&gt;Alter Ego&lt;/div&gt; &lt;div class="col-xs-9"&gt;{{ model.alterEgo }}&lt;/div&gt; &lt;/div&gt; &lt;div class="row"&gt; &lt;div class="col-xs-3"&gt;Power&lt;/div&gt; &lt;div class="col-xs-9"&gt;{{ model.power }}&lt;/div&gt; &lt;/div&gt; &lt;br&gt; &lt;button class="btn btn-primary" (click)="submitted=false"&gt;Edit&lt;/button&gt; &lt;/div&gt;</div><header class="ng-star-inserted">src/app/hero-form/hero-form.component.html (excerpt)</header><aio-code class="headed-code"><pre class="prettyprint lang-">      <button class="material-icons copy-button no-print ng-star-inserted" title="Copy code snippet" aria-label="Copy code snippet from src/app/hero-form/hero-form.component.html (excerpt)">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><span class="tag">&lt;div</span><span class="pln"> [</span><span class="atn">hidden</span><span class="pln">]</span><span class="pun">=</span><span class="atv">"!submitted"</span><span class="tag">&gt;</span><span class="pln">
  </span><span class="tag">&lt;h2&gt;</span><span class="pln">You submitted the following:</span><span class="tag">&lt;/h2&gt;</span><span class="pln">
  </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"row"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"col-xs-3"</span><span class="tag">&gt;</span><span class="pln">Name</span><span class="tag">&lt;/div&gt;</span><span class="pln">
    </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"col-xs-9"</span><span class="tag">&gt;</span><span class="pln">{{ model.name }}</span><span class="tag">&lt;/div&gt;</span><span class="pln">
  </span><span class="tag">&lt;/div&gt;</span><span class="pln">
  </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"row"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"col-xs-3"</span><span class="tag">&gt;</span><span class="pln">Alter Ego</span><span class="tag">&lt;/div&gt;</span><span class="pln">
    </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"col-xs-9"</span><span class="tag">&gt;</span><span class="pln">{{ model.alterEgo }}</span><span class="tag">&lt;/div&gt;</span><span class="pln">
  </span><span class="tag">&lt;/div&gt;</span><span class="pln">
  </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"row"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"col-xs-3"</span><span class="tag">&gt;</span><span class="pln">Power</span><span class="tag">&lt;/div&gt;</span><span class="pln">
    </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"col-xs-9"</span><span class="tag">&gt;</span><span class="pln">{{ model.power }}</span><span class="tag">&lt;/div&gt;</span><span class="pln">
  </span><span class="tag">&lt;/div&gt;</span><span class="pln">
  </span><span class="tag">&lt;br&gt;</span><span class="pln">
  </span><span class="tag">&lt;button</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"btn btn-primary"</span><span class="pln"> (</span><span class="atn">click</span><span class="pln">)</span><span class="pun">=</span><span class="atv">"submitted=false"</span><span class="tag">&gt;</span><span class="pln">Edit</span><span class="tag">&lt;/button&gt;</span><span class="pln">
</span><span class="tag">&lt;/div&gt;</span></code>
    </pre></aio-code></code-example><p translation-result="on">英雄又出现了，它通过插值表达式绑定显示为只读内容。 这一小段 HTML 只在组件处于已提交状态时才会显示。</p><p translation-origin="off">There's the hero again, displayed read-only with interpolation bindings. This <code>&lt;div&gt;</code> appears only while the component is in the submitted state.</p><p translation-result="on">这段 HTML 包含一个 “Edit（编辑）”按钮，它的 click 事件绑定到了一个用于清除 <code>submitted</code> 标志的表达式。</p><p translation-origin="off">The HTML includes an <em>Edit</em> button whose click event is bound to an expression that clears the <code>submitted</code> flag.</p><p translation-result="on">当点 <em>Edit</em> 按钮时，这个只读块消失了，可编辑的表单重新出现了。</p><p translation-origin="off">When you click the <em>Edit</em> button, this block disappears and the editable form reappears.</p><h2 id="summary" translation-result="on">小结<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#summary"><i class="material-icons">link</i></a></h2><h2 translation-origin="off" id="summary">Summary<a title="Link to this heading" class="header-link" aria-hidden="true" href="guide/forms#summary"><i class="material-icons">link</i></a></h2><p translation-result="on">本章讨论的 Angular 表单技术利用了下列框架特性来支持数据修改、验证和更多操作：</p><p translation-origin="off">The Angular form discussed in this page takes advantage of the following framework features to provide support for data modification, validation, and more:</p><ul><li><p translation-result="on">Angular HTML 表单模板。</p><p translation-origin="off">An Angular HTML form template.</p></li><li><p translation-result="on">带有 <code>@<a href="api/core/Component" class="code-anchor">Component</a></code> 装饰器的表单组件类。</p><p translation-origin="off">A form component class with a <code>@<a href="api/core/Component" class="code-anchor">Component</a></code> decorator.</p></li><li><p translation-result="on">通过绑定到 <code><a href="api/forms/NgForm#ngSubmit" class="code-anchor">NgForm.ngSubmit</a></code> 事件属性来处理表单提交。</p><p translation-origin="off">Handling form submission by binding to the <code><a href="api/forms/NgForm#ngSubmit" class="code-anchor">NgForm.ngSubmit</a></code> event property.</p></li><li><p translation-result="on">模板引用变量，例如 <code>#heroForm</code> 和 <code>#name</code>。</p><p translation-origin="off">Template-reference variables such as <code>#heroForm</code> and <code>#name</code>.</p></li><li><p translation-result="on"> <code>[(<a href="api/forms/NgModel" class="code-anchor">ngModel</a>)]</code> 语法用来实现双向数据绑定。</p><p translation-origin="off"><code>[(<a href="api/forms/NgModel" class="code-anchor">ngModel</a>)]</code> syntax for two-way data binding.</p></li><li><p translation-result="on"> <code>name</code> 属性的用途是有效性验证和对表单元素的变更进行追踪。</p><p translation-origin="off">The use of <code>name</code> attributes for validation and form-element change tracking.</p></li><li><p translation-result="on">指向 input 控件的引用变量上的 <code>valid</code> 属性，可用于检查控件是否有效、是否显示/隐藏错误信息。</p><p translation-origin="off">The reference variable’s <code>valid</code> property on input controls to check if a control is valid and show/hide error messages.</p></li><li><p translation-result="on">通过绑定到 <code><a href="api/forms/NgForm" class="code-anchor">NgForm</a></code> 的有效性状态，控制 <em>Submit</em> 按钮的禁用状态。</p><p translation-origin="off">Controlling the <em>Submit</em> button's enabled state by binding to <code><a href="api/forms/NgForm" class="code-anchor">NgForm</a></code> validity.</p></li><li><p translation-result="on">定制 CSS 类来给用户提供无效控件的视觉反馈。</p><p translation-origin="off">Custom CSS classes that provide visual feedback to users about invalid controls.</p></li></ul><p translation-result="on">下面是该应用最终版本的代码：</p><p translation-origin="off">Here’s the code for the final version of the application:</p><code-tabs ng-version="7.0.0"><div style="display:none"><code-pane header="hero-form/hero-form.component.ts" path="forms/src/app/hero-form/hero-form.component.ts" region="final">import { <a href="api/core/Component" class="code-anchor">Component</a> } from '@angular/core'; import { Hero } from '../hero'; @<a href="api/core/Component" class="code-anchor">Component</a>({ selector: 'app-hero-form', templateUrl: './hero-form.component.html', <a href="api/core/Component#styleUrls" class="code-anchor">styleUrls</a>: ['./hero-form.component.css'] }) export class HeroFormComponent { powers = ['Really Smart', 'Super Flexible', 'Super Hot', 'Weather Changer']; <a href="api/forms/NgModel#model" class="code-anchor">model</a> = new Hero(18, 'Dr IQ', this.powers[0], 'Chuck Overstreet'); submitted = false; onSubmit() { this.submitted = true; } newHero() { this.model = new Hero(42, '', ''); } }</code-pane><code-pane header="hero-form/hero-form.component.html" path="forms/src/app/hero-form/hero-form.component.html" region="final">&lt;div class="container"&gt; &lt;div [hidden]="submitted"&gt; &lt;h1&gt;Hero <a href="api/forms/Form" class="code-anchor">Form</a>&lt;/h1&gt; &lt;form (ngSubmit)="onSubmit()" #heroForm="<a href="api/forms/NgForm" class="code-anchor">ngForm</a>"&gt; &lt;div class="form-group"&gt; &lt;label for="name"&gt;Name&lt;/label&gt; &lt;input type="text" class="form-control" id="name" required [(<a href="api/forms/NgModel" class="code-anchor">ngModel</a>)]="model.name" name="name" #name="<a href="api/forms/NgModel" class="code-anchor">ngModel</a>"&gt; &lt;div [hidden]="name.valid || name.pristine" class="alert alert-danger"&gt; Name is required &lt;/div&gt; &lt;/div&gt; &lt;div class="form-group"&gt; &lt;label for="alterEgo"&gt;Alter Ego&lt;/label&gt; &lt;input type="text" class="form-control" id="alterEgo" [(<a href="api/forms/NgModel" class="code-anchor">ngModel</a>)]="model.alterEgo" name="alterEgo"&gt; &lt;/div&gt; &lt;div class="form-group"&gt; &lt;label for="power"&gt;Hero Power&lt;/label&gt; &lt;select class="form-control" id="power" required [(<a href="api/forms/NgModel" class="code-anchor">ngModel</a>)]="model.power" name="power" #power="<a href="api/forms/NgModel" class="code-anchor">ngModel</a>"&gt; &lt;<a href="api/forms/NgSelectOption" class="code-anchor">option</a> *<a href="api/common/NgForOf" class="code-anchor">ngFor</a>="let pow of powers" [value]="pow"&gt;{{pow}}&lt;/<a href="api/forms/NgSelectOption" class="code-anchor">option</a>&gt; &lt;/select&gt; &lt;div [hidden]="power.valid || power.pristine" class="alert alert-danger"&gt; Power is required &lt;/div&gt; &lt;/div&gt; &lt;button type="submit" class="btn btn-success" [disabled]="!heroForm.form.valid"&gt;Submit&lt;/button&gt; &lt;button type="button" class="btn btn-default" (click)="newHero(); heroForm.reset()"&gt;New Hero&lt;/button&gt; &lt;/form&gt; &lt;/div&gt; &lt;div [hidden]="!submitted"&gt; &lt;h2&gt;You submitted the following:&lt;/h2&gt; &lt;div class="row"&gt; &lt;div class="col-xs-3"&gt;Name&lt;/div&gt; &lt;div class="col-xs-9"&gt;{{ model.name }}&lt;/div&gt; &lt;/div&gt; &lt;div class="row"&gt; &lt;div class="col-xs-3"&gt;Alter Ego&lt;/div&gt; &lt;div class="col-xs-9"&gt;{{ model.alterEgo }}&lt;/div&gt; &lt;/div&gt; &lt;div class="row"&gt; &lt;div class="col-xs-3"&gt;Power&lt;/div&gt; &lt;div class="col-xs-9"&gt;{{ model.power }}&lt;/div&gt; &lt;/div&gt; &lt;br&gt; &lt;button class="btn btn-primary" (click)="submitted=false"&gt;Edit&lt;/button&gt; &lt;/div&gt; &lt;/div&gt;</code-pane><code-pane header="hero.ts" path="forms/src/app/hero.ts">export class Hero { constructor( public id: number, public name: string, public power: string, public alterEgo?: string ) { } }</code-pane><code-pane header="app.module.ts" path="forms/src/app/app.module.ts">import { <a href="api/core/NgModule" class="code-anchor">NgModule</a> } from '@angular/core'; import { <a href="api/platform-browser/BrowserModule" class="code-anchor">BrowserModule</a> } from '@angular/platform-browser'; import { <a href="api/forms/FormsModule" class="code-anchor">FormsModule</a> } from '@angular/forms'; import { AppComponent } from './app.component'; import { HeroFormComponent } from './hero-form/hero-form.component'; @<a href="api/core/NgModule" class="code-anchor">NgModule</a>({ <a href="api/core/NgModule#imports" class="code-anchor">imports</a>: [ <a href="api/platform-browser/BrowserModule" class="code-anchor">BrowserModule</a>, <a href="api/forms/FormsModule" class="code-anchor">FormsModule</a> ], <a href="api/core/NgModule#declarations" class="code-anchor">declarations</a>: [ AppComponent, HeroFormComponent ], providers: [], <a href="api/core/NgModule#bootstrap" class="code-anchor">bootstrap</a>: [ AppComponent ] }) export class AppModule { }</code-pane><code-pane header="app.component.html" path="forms/src/app/app.component.html">&lt;app-hero-form&gt;&lt;/app-hero-form&gt;</code-pane><code-pane header="app.component.ts" path="forms/src/app/app.component.ts">import { <a href="api/core/Component" class="code-anchor">Component</a> } from '@angular/core'; @<a href="api/core/Component" class="code-anchor">Component</a>({ selector: 'app-root', templateUrl: './app.component.html', <a href="api/core/Component#styleUrls" class="code-anchor">styleUrls</a>: ['./app.component.css'] }) export class AppComponent { }</code-pane><code-pane header="main.ts" path="forms/src/main.ts">import { <a href="api/core/enableProdMode" class="code-anchor">enableProdMode</a> } from '@angular/core'; import { <a href="api/platform-browser-dynamic/platformBrowserDynamic" class="code-anchor">platformBrowserDynamic</a> } from '@angular/platform-browser-dynamic'; import { AppModule } from './app/app.module'; import { environment } from './environments/environment'; if (environment.production) { <a href="api/core/enableProdMode" class="code-anchor">enableProdMode</a>(); } <a href="api/platform-browser-dynamic/platformBrowserDynamic" class="code-anchor">platformBrowserDynamic</a>().bootstrapModule(AppModule);</code-pane><code-pane header="forms.css" path="forms/src/assets/forms.css">.ng-valid[required], .ng-valid.required { border-left: 5px solid #42A948; /* green */ } .ng-invalid:not(form) { border-left: 5px solid #a94442; /* red */ }</code-pane></div><mat-card class="mat-card"><mat-tab-group class="code-tab-group mat-tab-group mat-primary" disableripple=""><mat-tab-header class="mat-tab-header mat-tab-header-pagination-controls-enabled"><div aria-hidden="true" class="mat-tab-header-pagination mat-tab-header-pagination-before mat-elevation-z4 mat-ripple mat-tab-header-pagination-disabled" mat-ripple=""><div class="mat-tab-header-pagination-chevron"></div></div><div class="mat-tab-label-container"><div class="mat-tab-list" role="tablist" style="transform:translateX(0)"><div class="mat-tab-labels"><div cdkmonitorelementfocus="" class="mat-tab-label mat-ripple mat-tab-label-active ng-star-inserted" mat-ripple="" mattablabelwrapper="" role="tab" id="mat-tab-label-0-0" tabindex="0" aria-posinset="1" aria-setsize="8" aria-controls="mat-tab-content-0-0" aria-selected="true" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">hero-form/hero-form.component.ts</span></div></div><div cdkmonitorelementfocus="" class="mat-tab-label mat-ripple ng-star-inserted" mat-ripple="" mattablabelwrapper="" role="tab" id="mat-tab-label-0-1" tabindex="-1" aria-posinset="2" aria-setsize="8" aria-controls="mat-tab-content-0-1" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">hero-form/hero-form.component.html</span></div></div><div cdkmonitorelementfocus="" class="mat-tab-label mat-ripple ng-star-inserted" mat-ripple="" mattablabelwrapper="" role="tab" id="mat-tab-label-0-2" tabindex="-1" aria-posinset="3" aria-setsize="8" aria-controls="mat-tab-content-0-2" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">hero.ts</span></div></div><div cdkmonitorelementfocus="" class="mat-tab-label mat-ripple ng-star-inserted" mat-ripple="" mattablabelwrapper="" role="tab" id="mat-tab-label-0-3" tabindex="-1" aria-posinset="4" aria-setsize="8" aria-controls="mat-tab-content-0-3" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">app.module.ts</span></div></div><div cdkmonitorelementfocus="" class="mat-tab-label mat-ripple ng-star-inserted" mat-ripple="" mattablabelwrapper="" role="tab" id="mat-tab-label-0-4" tabindex="-1" aria-posinset="5" aria-setsize="8" aria-controls="mat-tab-content-0-4" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">app.component.html</span></div></div><div cdkmonitorelementfocus="" class="mat-tab-label mat-ripple ng-star-inserted" mat-ripple="" mattablabelwrapper="" role="tab" id="mat-tab-label-0-5" tabindex="-1" aria-posinset="6" aria-setsize="8" aria-controls="mat-tab-content-0-5" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">app.component.ts</span></div></div><div cdkmonitorelementfocus="" class="mat-tab-label mat-ripple ng-star-inserted" mat-ripple="" mattablabelwrapper="" role="tab" id="mat-tab-label-0-6" tabindex="-1" aria-posinset="7" aria-setsize="8" aria-controls="mat-tab-content-0-6" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">main.ts</span></div></div><div cdkmonitorelementfocus="" class="mat-tab-label mat-ripple ng-star-inserted" mat-ripple="" mattablabelwrapper="" role="tab" id="mat-tab-label-0-7" tabindex="-1" aria-posinset="8" aria-setsize="8" aria-controls="mat-tab-content-0-7" aria-selected="false" aria-disabled="false"><div class="mat-tab-label-content"><span class="ng-star-inserted">forms.css</span></div></div></div><mat-ink-bar class="mat-ink-bar" style="visibility:visible;left:0;width:261px"></mat-ink-bar></div></div><div aria-hidden="true" class="mat-tab-header-pagination mat-tab-header-pagination-after mat-elevation-z4 mat-ripple" mat-ripple=""><div class="mat-tab-header-pagination-chevron"></div></div></mat-tab-header><div class="mat-tab-body-wrapper"><mat-tab-body class="mat-tab-body ng-tns-c12-2 mat-tab-body-active ng-star-inserted" role="tabpanel" id="mat-tab-content-0-0" aria-labelledby="mat-tab-label-0-0"><div class="mat-tab-body-content ng-trigger ng-trigger-translateTab" style="transform:none"><aio-code class="ng-star-inserted" style=""><pre class="prettyprint lang-">      <button class="material-icons copy-button no-print ng-star-inserted" title="Copy code snippet" aria-label="Copy code snippet from hero-form/hero-form.component.ts">
        <span aria-hidden="true">content_copy</span>
      </button>
      <code class="animated fadeIn"><ol class="linenums"><li class="L0"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><a href="api/core/Component" class="code-anchor"><span class="typ">Component</span></a><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'@angular/core'</span><span class="pun">;</span></li><li class="L1"><span class="pln">&nbsp;</span></li><li class="L2"><span class="kwd">import</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">Hero</span><span class="pln"> </span><span class="pun">}</span><span class="pln">    </span><span class="kwd">from</span><span class="pln"> </span><span class="str">'../hero'</span><span class="pun">;</span></li><li class="L3"><span class="pln">&nbsp;</span></li><li class="L4"><span class="lit">@</span><a href="api/core/Component" class="code-anchor"><span class="lit">Component</span></a><span class="pun">({</span></li><li class="L5"><span class="pln">  selector</span><span class="pun">:</span><span class="pln"> </span><span class="str">'app-hero-form'</span><span class="pun">,</span></li><li class="L6"><span class="pln">  templateUrl</span><span class="pun">:</span><span class="pln"> </span><span class="str">'./hero-form.component.html'</span><span class="pun">,</span></li><li class="L7"><span class="pln">  </span><a href="api/core/Component#styleUrls" class="code-anchor"><span class="pln">styleUrls</span></a><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="str">'./hero-form.component.css'</span><span class="pun">]</span></li><li class="L8"><span class="pun">})</span></li><li class="L9"><span class="kwd">export</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">HeroFormComponent</span><span class="pln"> </span><span class="pun">{</span></li><li class="L0"><span class="pln">&nbsp;</span></li><li class="L1"><span class="pln">  powers </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'Really Smart'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Super Flexible'</span><span class="pun">,</span></li><li class="L2"><span class="pln">            </span><span class="str">'Super Hot'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Weather Changer'</span><span class="pun">];</span></li><li class="L3"><span class="pln">&nbsp;</span></li><li class="L4"><span class="pln">  </span><a href="api/forms/NgModel#model" class="code-anchor"><span class="pln">model</span></a><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Hero</span><span class="pun">(</span><span class="lit">18</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Dr IQ'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">powers</span><span class="pun">[</span><span class="lit">0</span><span class="pun">],</span><span class="pln"> </span><span class="str">'Chuck Overstreet'</span><span class="pun">);</span></li><li class="L5"><span class="pln">&nbsp;</span></li><li class="L6"><span class="pln">  submitted </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span></li><li class="L7"><span class="pln">&nbsp;</span></li><li class="L8"><span class="pln">  onSubmit</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">submitted </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span></li><li class="L9"><span class="pln">&nbsp;</span></li><li class="L0"><span class="pln">  newHero</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span></li><li class="L1"><span class="pln">    </span><span class="kwd">this</span><span class="pun">.</span><span class="pln">model </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Hero</span><span class="pun">(</span><span class="lit">42</span><span class="pun">,</span><span class="pln"> </span><span class="str">''</span><span class="pun">,</span><span class="pln"> </span><span class="str">''</span><span class="pun">);</span></li><li class="L2"><span class="pln">  </span><span class="pun">}</span></li><li class="L3"><span class="pun">}</span></li></ol></code>
    </pre></aio-code></div></mat-tab-body><mat-tab-body class="mat-tab-body ng-tns-c12-3 ng-star-inserted" role="tabpanel" id="mat-tab-content-0-1" aria-labelledby="mat-tab-label-0-1"><div class="mat-tab-body-content ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body class="mat-tab-body ng-tns-c12-4 ng-star-inserted" role="tabpanel" id="mat-tab-content-0-2" aria-labelledby="mat-tab-label-0-2"><div class="mat-tab-body-content ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body class="mat-tab-body ng-tns-c12-5 ng-star-inserted" role="tabpanel" id="mat-tab-content-0-3" aria-labelledby="mat-tab-label-0-3"><div class="mat-tab-body-content ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body class="mat-tab-body ng-tns-c12-6 ng-star-inserted" role="tabpanel" id="mat-tab-content-0-4" aria-labelledby="mat-tab-label-0-4"><div class="mat-tab-body-content ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body class="mat-tab-body ng-tns-c12-7 ng-star-inserted" role="tabpanel" id="mat-tab-content-0-5" aria-labelledby="mat-tab-label-0-5"><div class="mat-tab-body-content ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body class="mat-tab-body ng-tns-c12-8 ng-star-inserted" role="tabpanel" id="mat-tab-content-0-6" aria-labelledby="mat-tab-label-0-6"><div class="mat-tab-body-content ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body><mat-tab-body class="mat-tab-body ng-tns-c12-9 ng-star-inserted" role="tabpanel" id="mat-tab-content-0-7" aria-labelledby="mat-tab-label-0-7"><div class="mat-tab-body-content ng-trigger ng-trigger-translateTab" style="transform:translate3d(100%,0,0);min-height:1px"></div></mat-tab-body></div></mat-tab-group></mat-card></code-tabs></div></div></aio-doc-viewer></main></mat-sidenav-content></mat-sidenav-container><div class="toc-container no-print ng-star-inserted"><aio-lazy-ce selector="aio-toc"><aio-toc ng-version="7.0.0"><div class="toc-inner no-print collapsed ng-star-inserted"><ul class="toc-list"><li title="表单link" class="h1 ng-star-inserted active"><a href="guide/forms#template-driven-forms">表单</a></li><li title="模板驱动表单简介link" class="h2 ng-star-inserted"><a href="guide/forms#introduction-to-template-driven-forms">模板驱动表单简介</a></li><li title="模板驱动表单link" class="h2 ng-star-inserted"><a href="guide/forms#template-driven-forms-1">模板驱动表单</a></li><li title="准备工作link" class="h2 ng-star-inserted"><a href="guide/forms#setup">准备工作</a></li><li title="创建 Hero 模型类link" class="h2 ng-star-inserted"><a href="guide/forms#create-the-hero-model-class">创建 Hero 模型类</a></li><li title="创建表单组件link" class="h2 ng-star-inserted"><a href="guide/forms#create-a-form-component">创建表单组件</a></li><li title="修改 app.module.tslink" class="h2 ng-star-inserted"><a href="guide/forms#revise-appmodulets">修改 <em>app.module.ts</em></a></li><li title="修改 app.component.tslink" class="h2 ng-star-inserted"><a href="guide/forms#revise-appcomponenthtml">修改 <em>app.component.ts</em></a></li><li title="创建初始 HTML 表单模板link" class="h2 ng-star-inserted"><a href="guide/forms#create-an-initial-html-form-template">创建初始 HTML 表单模板</a></li><li title="用 ngFor 添加超能力link" class="h2 ng-star-inserted"><a href="guide/forms#add-powers-with-ngfor">用 <strong><em>ngFor</em></strong> 添加超能力</a></li><li title="使用 ngModel 进行双向数据绑定link" class="h2 ng-star-inserted"><a href="guide/forms#two-way-data-binding-with-ngmodel">使用 <em>ngModel</em> 进行双向数据绑定</a></li><li title="NgForm 指令link" class="h3 ng-star-inserted"><a href="guide/forms#the-ngform-directive"><em>NgForm</em> 指令</a></li><li title="通过 ngModel 跟踪修改状态与有效性验证link" class="h2 ng-star-inserted"><a href="guide/forms#track-control-state-and-validity-with-ngmodel">通过 <strong>ngModel</strong> 跟踪修改状态与有效性验证</a></li><li title="添加用于视觉反馈的自定义 CSSlink" class="h2 ng-star-inserted"><a href="guide/forms#add-custom-css-for-visual-feedback">添加用于视觉反馈的自定义 CSS</a></li><li title="显示和隐藏验证错误信息link" class="h2 ng-star-inserted"><a href="guide/forms#show-and-hide-validation-error-messages">显示和隐藏验证错误信息</a></li><li title="使用 ngSubmit 提交该表单link" class="h2 ng-star-inserted"><a href="guide/forms#submit-the-form-with-ngsubmit">使用 <em>ngSubmit</em> 提交该表单</a></li><li title="切换两个表单区域（额外的奖励）link" class="h2 ng-star-inserted"><a href="guide/forms#toggle-two-form-regions-extra-credit">切换两个表单区域（额外的奖励）</a></li><li title="小结link" class="h2 ng-star-inserted"><a href="guide/forms#summary">小结</a></li></ul></div></aio-toc></aio-lazy-ce></div><footer class="no-print"><aio-footer><div class="grid-fluid"><div class="footer-block ng-star-inserted"><h3>资源</h3><ul><li class="ng-star-inserted"><a class="link" href="about" title="Angular 贡献者。">关于</a></li><li class="ng-star-inserted"><a class="link" href="resources" title="网络上的 Angular 工具、培训、博客等">资源列表</a></li><li class="ng-star-inserted"><a class="link" href="presskit" title="我们的联系方式、LOGO 和品牌">宣传资料</a></li><li class="ng-star-inserted"><a class="link" href="https://blog.angular.io/" title="Angular 官方博客">博客</a></li></ul></div><div class="footer-block ng-star-inserted"><h3>帮助</h3><ul><li class="ng-star-inserted"><a class="link" href="https://stackoverflow.com/questions/tagged/angular" title="Stack Overflow: 这里的社区会回答你关于 Angular 的技术问题">Stack Overflow</a></li><li class="ng-star-inserted"><a class="link" href="https://gitter.im/angular/angular" title="和老鸟聊 Angular">Gitter</a></li><li class="ng-star-inserted"><a class="link" href="https://github.com/angular/angular/issues" title="在 github 上报告问题和建议。">报告问题</a></li><li class="ng-star-inserted"><a class="link" href="https://github.com/angular/code-of-conduct/blob/master/CODE_OF_CONDUCT.md" title="让我们彼此尊重">行为规范</a></li></ul></div><div class="footer-block ng-star-inserted"><h3>社区</h3><ul><li class="ng-star-inserted"><a class="link" href="events" title="Post issues and suggestions on github.">活动</a></li><li class="ng-star-inserted"><a class="link" href="http://www.meetup.com/topics/angularjs/" title="参加聚会，向别的开发人员学习">聚会</a></li><li class="ng-star-inserted"><a class="link" href="https://twitter.com/angular" title="Twitter">Twitter</a></li><li class="ng-star-inserted"><a class="link" href="https://github.com/angular/angular" title="GitHub">GitHub</a></li><li class="ng-star-inserted"><a class="link" href="contribute" title="向 Angular 做贡献">做贡献</a></li></ul></div><div class="footer-block ng-star-inserted"><h3>多语言</h3><ul><li class="ng-star-inserted"><a class="link" href="https://angular.io/" title="English Version.">English Version</a></li><li class="ng-star-inserted"><a class="link" href="https://angular.jp/" title="日本語版">日本語版</a></li><li class="ng-star-inserted"><a class="link" href="https://angular.kr/" title="한국어">한국어</a></li></ul></div></div><p>Super-powered by Google ©2010-2019. 代码授权方式：<a href="license" title="License text">MIT-style License</a>. 文档授权方式：<a href="http://creativecommons.org/licenses/by/4.0/">CC BY 4.0</a>.</p><p>当前版本：8.0.0-build.95+sha.43aadf1.</p></aio-footer></footer><mat-icon class="cdk-visually-hidden mat-icon material-icons ng-star-inserted" role="img" aria-hidden="true">&nbsp;</mat-icon></aio-shell><noscript><div class="background-sky hero"></div><section id="intro" style="text-shadow:1px 1px #1976d2"><div class="hero-logo"><img src="assets/images/logos/angular/angular.svg" width="250" height="250" alt="Angular"></div><div class="homepage-container"><div class="hero-headline">一套框架，多种平台<br>移动 &amp; 桌面</div></div></section><h2 style="color:red;margin-top:40px;position:relative;text-align:center;text-shadow:1px 1px #fafafa"><b><i>该网站需要浏览器支持 JavaScript</i></b></h2></noscript><script src="runtime.fa3355727d5250409e08.js"></script><script src="polyfills.a2efc1c1a62312ff1f80.js"></script><script src="main.02884fe4cde5ede2ec4e.js"></script><div class="cdk-live-announcer-element cdk-visually-hidden" aria-atomic="true" aria-live="polite"></div></body></html>